diff --git a/.appveyor.yml b/.appveyor.yml index 54ad4f01b..8d2b2e6df 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -8,14 +8,17 @@ skip_tags: true skip_commits: files: - - .drone.yml + - .drone.star - .github/** - - .travis.yml + - android/** - docs/** - src/**/*_posix.* - src/**/*_linux.* + - src/**/*_gnulinux.* - src/**/*_x11.* - src/**/*_gtk.* + - src/**/*_android.* + - src/**/*_mac.* - LICENSE - README.md @@ -27,23 +30,28 @@ pull_requests: os: Visual Studio 2019 init: - - git config --global core.autocrlf input + - ps: | + If (-Not $env:APPVEYOR_PULL_REQUEST_NUMBER) { + $env:is_not_pr = "true" + } + If (-Not $env:APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED) { + $env:APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED = " " + } install: - - cmd: vcpkg integrate remove - - cmd: xb setup + - | + vcpkg integrate remove + xb setup platform: Windows -configuration: - - Release - - Checked +configuration: [Release, Checked] build_script: - - cmd: xb build --config=%CONFIGURATION% --target=src\xenia-app --target=tests\xenia-base-tests --target=tests\xenia-cpu-ppc-tests --target=src\xenia-vfs-dump + - xb build --config=%CONFIGURATION% --target=src\xenia-app --target=tests\xenia-base-tests --target=tests\xenia-cpu-ppc-tests --target=src\xenia-vfs-dump after_build: - - cmd: | + - | IF NOT "%CONFIGURATION%"=="Checked" SET "ARCHIVE_SUFFIX=%APPVEYOR_REPO_BRANCH%" IF NOT "%CONFIGURATION%"=="Checked" SET "ARCHIVE_SWITCHES=--" IF "%CONFIGURATION%"=="Checked" SET "ARCHIVE_SUFFIX=%APPVEYOR_REPO_BRANCH%_FOR-DEVS-ONLY" @@ -52,10 +60,10 @@ after_build: 7z a xenia-vfs-dump_%ARCHIVE_SUFFIX%.zip %ARCHIVE_SWITCHES% LICENSE "%APPVEYOR_BUILD_FOLDER%\build\bin\%PLATFORM%\%CONFIGURATION%\xenia-vfs-dump.exe" "%APPVEYOR_BUILD_FOLDER%\build\bin\%PLATFORM%\%CONFIGURATION%\xenia-vfs-dump.pdb" before_test: - - cmd: xb gentests + - xb gentests test_script: - - cmd: xb test --config=%CONFIGURATION% --no_build + - xb test --config=%CONFIGURATION% --no_build artifacts: - path: '*.zip' @@ -73,3 +81,22 @@ deploy: configuration: release appveyor_repo_tag: true is_not_pr: true + - provider: GitHub + name: xenia-master + repository: xenia-project/release-builds-windows + auth_token: + secure: /8he47z1WnPN7LcCTe5T5KMxxX0SmqFj9QMpeWEa3aZ64kMsfupOT/jKakqTM8af + tag: v$(appveyor_build_version) + release: v$(appveyor_build_version) + description: | + Windows release build for https://github.com/xenia-project/xenia/commit/$(APPVEYOR_REPO_COMMIT). + + $(APPVEYOR_REPO_COMMIT_MESSAGE) + + $(APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED) + draft: false + prerelease: false + on: + branch: master + configuration: release + is_not_pr: true diff --git a/.drone.star b/.drone.star new file mode 100644 index 000000000..50b5c9ec3 --- /dev/null +++ b/.drone.star @@ -0,0 +1,451 @@ +def main(ctx): + return [ + pipeline_lint(), + pipeline_linux_desktop('x86_64-linux-clang', image_linux_x86_64(), 'amd64', 'clang', True), + pipeline_linux_desktop('x86_64-linux-gcc', image_linux_x86_64(), 'amd64', 'gcc', False), # GCC release linking is really slow + pipeline_android('x86_64-android', image_linux_x86_64(), 'amd64', 'Android-x86_64'), + pipeline_android('aarch64-android', image_linux_x86_64(), 'amd64', 'Android-ARM64'), + ] + +def image_linux_x86_64(): + return 'xeniaproject/buildenv:2022-01-01' + +def volume_build(toolchain, path='/drone/src/build'): + return { + 'name': 'build-' + toolchain, + 'path': path, + } + +def command_cc(cc): + # set CC, CXX, ... + return 'export $(cat /{}.env | sed \'s/#.*//g\' | xargs)'.format(cc) + +def command_ndk_build(platform, configuration, target): + return '$ANDROID_NDK_ROOT/build/ndk-build NDK_PROJECT_PATH:=./bin/{configuration} NDK_APPLICATION_MK:=./xenia.Application.mk PREMAKE_ANDROIDNDK_PLATFORMS:={platform} PREMAKE_ANDROIDNDK_CONFIGURATIONS:={configuration} -j$(nproc) {target}'.format(platform=platform, configuration=configuration, target=target) + +def targets_android(platform): + targets = [ + 'aes_128', + 'capstone', + 'dxbc', + 'discord-rpc', + 'cxxopts', + 'cpptoml', + 'avcodec', + 'avutil', + 'fmt', + 'glslang-spirv', + 'imgui', + 'mspack', + 'snappy', + 'spirv-tools', + 'xxhash', + # 'xenia-core', + # 'xenia-app-discord', + # 'xenia-apu', + # 'xenia-apu-nop', + 'xenia-base', + 'xenia-base-tests', + # 'xenia-cpu', + # 'xenia-cpu-tests', + # 'xenia-cpu-ppc-tests', + # 'xenia-cpu-backend-x64', + # 'xenia-debug-ui', + # 'xenia-gpu', + # 'xenia-gpu-shader-compiler', + # 'xenia-gpu-null', + # 'xenia-gpu-vulkan', + # 'xenia-gpu-vulkan-trace-viewer', + # 'xenia-gpu-vulkan-trace-dump', + 'xenia-hid', + # 'xenia-hid-demo', + 'xenia-hid-nop', + # 'xenia-kernel', + 'xenia-ui', + 'xenia-ui-spirv', + # 'xenia-ui-vulkan', + # 'xenia-ui-window-vulkan-demo', + 'xenia-vfs', + 'xenia-vfs-dump', + ] + if platform == 'Android-x86_64': + targets.extend([ + 'xenia-core', + 'xenia-apu', + 'xenia-apu-nop', + 'xenia-cpu', + 'xenia-cpu-tests', + 'xenia-cpu-ppc-tests', + 'xenia-cpu-backend-x64', + 'xenia-debug-ui', + 'xenia-gpu', + 'xenia-gpu-null', + 'xenia-gpu-vulkan', + 'xenia-gpu-shader-compiler', + 'xenia-kernel', + ]) + return targets + +# Run lint in a separate pipeline so that it will try building even if lint fails +def pipeline_lint(): + return { + 'kind': 'pipeline', + 'type': 'docker', + 'name': 'lint', + 'steps': [ + { + 'name': 'lint', + 'image': image_linux_x86_64(), + 'commands': [ + 'clang-format --version', + './xenia-build lint --all', + ], + }, + ], + } + +def pipeline_linux_desktop(name, image, arch, cc, build_release_all): + return { + 'kind': 'pipeline', + 'type': 'docker', + 'name': name, + 'platform': { + 'os': 'linux', + 'arch': arch, + }, + # These volumes will be mounted at the build directory, allowing to + # run different premake toolchains from the same source tree + 'volumes': [ + { + 'name': 'build-premake', + 'temp': {}, + }, + { + 'name': 'build-cmake', + 'temp': {}, + }, + ], + + 'steps': [ + # + # Setup the source tree + # + { + 'name': 'clone-submodules', + 'image': image, + 'commands': [ + 'pwd', + # May miss recursive submodules (but faster than xb setup) + 'git submodule update --init --depth 1 -j $(nproc)', + ], + }, + + + # + # Setup the two build systems + # + + # Native premake Makefiles for production + { + 'name': 'toolchain-premake', + 'image': image, + 'volumes': [volume_build('premake')], + 'commands': [ + command_cc(cc), + '$CXX --version', + 'python3 --version', + './xenia-build premake --cc={}'.format(cc), + ], + 'depends_on': ['clone-submodules'], + }, + + # Development toolchain + { + 'name': 'toolchain-cmake', + 'image': image, + 'volumes': [volume_build('cmake')], + 'commands': [ + command_cc(cc), + ''' + ./xenia-build premake --cc={} --devenv=cmake + cd build + for c in Debug Release + do + mkdir cmake-$c + cd cmake-$c + cmake -DCMAKE_BUILD_TYPE=$c .. + cd .. + done + '''.format(cc), + ], + # Premake itself needs to be build first: + 'depends_on': ['toolchain-premake'], + }, + + # + # Building + # + + { + 'name': 'build-premake-debug-tests', + 'image': image, + 'volumes': [volume_build('premake')], + 'commands': [ + command_cc(cc), + './xenia-build build --no_premake -j$(nproc) --config=Debug --target=xenia-base-tests', + ], + 'depends_on': ['toolchain-premake'], + }, + { + 'name': 'build-premake-debug-all', + 'image': image, + 'volumes': [volume_build('premake')], + 'commands': [ + command_cc(cc), + './xenia-build build --no_premake -j$(nproc) --config=Debug', + ], + 'depends_on': ['build-premake-debug-tests'], + }, + + { + 'name': 'build-premake-release-tests', + 'image': image, + 'volumes': [volume_build('premake')], + 'commands': [ + command_cc(cc), + './xenia-build build --no_premake -j$(nproc) --config=Release --target=xenia-base-tests', + ], + 'depends_on': ['toolchain-premake'], + }, + ] + ([ + { + 'name': 'build-premake-release-all', + 'image': image, + 'volumes': [volume_build('premake')], + 'commands': [ + command_cc(cc), + './xenia-build build --no_premake -j$(nproc) --config=Release', + ], + 'depends_on': ['build-premake-release-tests'], + }, + ] if build_release_all else []) + [ + + { + 'name': 'build-cmake-debug-all', + 'image': image, + 'volumes': [volume_build('cmake')], + 'commands': [ + command_cc(cc), + 'cd build/cmake-Debug', + 'cmake --build . -j$(nproc)', + ], + 'depends_on': ['toolchain-cmake'], + }, + + { + 'name': 'build-cmake-release-tests', + 'image': image, + 'volumes': [volume_build('cmake')], + 'commands': [ + command_cc(cc), + 'cd build/cmake-Release', + 'cmake --build . -j$(nproc) --target xenia-base-tests', + ], + 'depends_on': ['toolchain-cmake'], + }, + ] + ([ + { + 'name': 'build-cmake-release-all', + 'image': image, + 'volumes': [volume_build('cmake')], + 'commands': [ + command_cc(cc), + 'cd build/cmake-Release', + 'cmake --build . -j$(nproc)', + ], + 'depends_on': ['build-cmake-release-tests'], + }, + ] if build_release_all else []) + [ + + + # + # Tests + # + + { + 'name': 'test-premake-debug-valgrind', + 'image': image, + 'volumes': [volume_build('premake')], + 'commands': [ + 'valgrind --error-exitcode=99 ./build/bin/Linux/Debug/xenia-base-tests', + ], + 'depends_on': ['build-premake-debug-tests'], + }, + + { + 'name': 'test-premake-release', + 'image': image, + 'volumes': [volume_build('premake')], + 'commands': [ + './build/bin/Linux/Release/xenia-base-tests', + ], + 'depends_on': ['build-premake-release-tests'], + }, + + { + 'name': 'test-cmake-release', + 'image': image, + 'volumes': [volume_build('cmake')], + 'commands': [ + './build/bin/Linux/Release/xenia-base-tests', + ], + 'depends_on': ['build-cmake-release-tests'], + }, + + + # + # Stat + # + + { + 'name': 'stat', + 'image': image, + 'volumes': [ + volume_build('premake', '/build-premake'), + volume_build('cmake', '/build-cmake'), + ], + 'commands': [ + ''' + header() { + SEP='============================================================' + echo + echo $SEP + echo $@ + echo $SEP + } + + for v in premake cmake + do + for c in Debug Release + do + header $v $c + p=/build-$v/bin/Linux/$c + ls -la $p + sha256sum $p/* + done + done + ''' + ], + 'depends_on': [ + 'build-premake-debug-all', + 'build-cmake-debug-all', + ] + ([ + 'build-premake-release-all', + 'build-cmake-release-all', + ] if build_release_all else [ + 'build-premake-release-tests', + 'build-cmake-release-tests', + ]), + }, + ], + } + + +def pipeline_android(name, image, arch, platform): + return { + 'kind': 'pipeline', + 'type': 'docker', + 'name': name, + 'platform': { + 'os': 'linux', + 'arch': arch, + }, + + 'steps': [ + # + # Setup the source tree + # + { + 'name': 'clone-submodules', + 'image': image, + 'commands': [ + 'pwd', + # May miss recursive submodules (but faster than xb setup) + 'git submodule update --init --depth 1 -j $(nproc)', + ], + }, + + + # + # Build premake and generate NDK makefiles + # + + # NDK Makefiles + { + 'name': 'toolchain', + 'image': image, + 'commands': [ + 'c++ --version', + 'python3 --version', + './xenia-build premake --target_os android', + ], + 'depends_on': ['clone-submodules'], + }, + + + # + # Building + # + { + 'name': 'build-debug', + 'image': image, + 'commands': [ + 'cd build', + command_ndk_build(platform, 'Debug', ' '.join(targets_android(platform))), + ], + 'depends_on': ['toolchain'], + }, + + { + 'name': 'build-release', + 'image': image, + 'commands': [ + 'cd build', + command_ndk_build(platform, 'Release', ' '.join(targets_android(platform))), + ], + 'depends_on': ['toolchain'], + }, + + + # + # Stat + # + { + 'name': 'stat', + 'image': image, + 'commands': [ + ''' + header() { + SEP='============================================================' + echo + echo $SEP + echo $@ + echo $SEP + } + + for c in Debug Release + do + header $c + p=build/bin/$c/obj/local/* + ls -la $p + sha256sum $p/* || true + done + ''' + ], + 'depends_on': [ + 'build-debug', + 'build-release', + ], + }, + ], + } diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index a8c2c21d3..000000000 --- a/.drone.yml +++ /dev/null @@ -1,214 +0,0 @@ ---- -kind: pipeline -type: docker -name: lint - -# Run this in a separate pipeline so that it will build even if this fails -steps: -- name: lint - image: xeniaproject/buildenv:2021-06-21 - commands: - - clang-format --version - - ./xenia-build lint --all - ---- -kind: pipeline -type: docker -name: x86_64-linux -platform: - os: linux - arch: amd64 - -# Some expressions in this file are duplicates. Scripting support is -# available using jsonnet but increases complexity -# https://docs.drone.io/pipeline/scripting/jsonnet/ - -# These volumes will be mounted at the build directory, allowing to -# run different premake toolchains from the same source tree -volumes: -- name: build-premake - temp: {} -- name: build-cmake - temp: {} - -steps: -# -# Setup the source tree -# -- name: clone-submodules - image: xeniaproject/buildenv:2021-06-21 - commands: - - pwd - # May miss recursive submodules (but faster than xb setup) - - git submodule update --init --depth 1 -j $(nproc) - - -# -# Setup the two build systems -# - -# Native premake Makefiles for production -- name: toolchain-premake - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-premake - path: /drone/src/build - commands: - - $CXX --version - - $AR --version - - python3 --version - - ./xenia-build premake - depends_on: - - clone-submodules - -# Development toolchain -- name: toolchain-cmake - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-cmake - path: /drone/src/build - commands: - - | - ./xenia-build premake --devenv=cmake - cd build - for c in Debug Release - do - mkdir cmake-$c - cd cmake-$c - cmake -DCMAKE_BUILD_TYPE=$c .. - cd .. - done - depends_on: - # Premake itself needs to be build first: - - toolchain-premake - - -# -# Building -# - -- name: build-premake-debug-all - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-premake - path: /drone/src/build - commands: - - ./xenia-build build --no_premake -j$(nproc) --config=Debug - depends_on: - - toolchain-premake - -- name: build-premake-release-tests - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-premake - path: /drone/src/build - commands: - - ./xenia-build build --no_premake -j$(nproc) --config=Release --target=xenia-base-tests - depends_on: - - toolchain-premake - -- name: build-premake-release-all - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-premake - path: /drone/src/build - commands: - - ./xenia-build build --no_premake -j$(nproc) --config=Release - depends_on: - - build-premake-release-tests - -- name: build-cmake-debug-all - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-cmake - path: /drone/src/build - commands: - - cd build/cmake-Debug - - cmake --build . -j$(nproc) - depends_on: - - toolchain-cmake - -- name: build-cmake-release-tests - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-cmake - path: /drone/src/build - commands: - - cd build/cmake-Release - - cmake --build . -j$(nproc) --target xenia-base-tests - depends_on: - - toolchain-cmake - -- name: build-cmake-release-all - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-cmake - path: /drone/src/build - commands: - - cd build/cmake-Release - - cmake --build . -j$(nproc) - depends_on: - - build-cmake-release-tests - - -# -# Tests -# - -- name: test-premake - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-premake - path: /drone/src/build - commands: - - ./build/bin/Linux/Release/xenia-base-tests - depends_on: - - build-premake-release-tests - -- name: test-cmake - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-cmake - path: /drone/src/build - commands: - - ./build/bin/Linux/Release/xenia-base-tests - depends_on: - - build-cmake-release-tests - - -# -# Stat -# - -- name: stat - image: xeniaproject/buildenv:2021-06-21 - volumes: - - name: build-premake - path: /build-premake - - name: build-cmake - path: /build-cmake - commands: - - | - header() { - SEP='============================================================' - echo - echo $SEP - echo $@ - echo $SEP - } - - for v in premake cmake - do - for c in Debug Release - do - header $v $c - p=/build-$v/bin/Linux/$c - ls -la $p - sha256sum $p/* - done - done - depends_on: - - build-premake-debug-all - - build-premake-release-all - - build-cmake-debug-all - - build-cmake-release-all diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 62bcd516c..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -patreon: xenia_project -github: [gibbed, JoelLinn, Razzile] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 673faa6af..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Bug report -about: Template for bug reports. -title: '' -labels: '' -assignees: '' - ---- - - - -[//]: # (Describe what's going wrong:) - -[//]: # (Describe what should happen:) - -[//]: # (If applicable, provide a callstack here - esp. for crashes) - -[//]: # (If applicable, upload a logfile and link it here) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 000000000..949966176 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,54 @@ +name: Bug report +description: Template for bug reports. +title: 'Bug: ' +body: + - type: markdown + attributes: + value: | + Try to create a very concise title that's straight to the point. + + **THIS IS NOT A SUPPORT FORUM!** For support, first read the wiki: https://github.com/xenia-project/xenia/wiki + If your question wasn't answered there or you need help, proceed to #help in the Discord server: https://discord.gg/Q9mxZf9 + + DO NOT CREATE ISSUES ABOUT SPECIFIC GAMES IN THIS REPOSITORY! + A game specific issue would be e.g. "Game X crashes after you hit a character a certain way" + A Xenia issue would be e.g. "Kernel export NtDoSomething does nothing" + For specific games, visit https://github.com/xenia-project/game-compatibility#game-compatibility + - type: checkboxes + id: validation + attributes: + label: Validation + options: + - label: I've read the [FAQ](https://github.com/xenia-project/xenia/wiki/FAQ). + required: true + - label: The Xenia build used is from the master branch (not MLBS/AlexVS/Canary/pull requests, etc.) + required: true + - label: This issue isn't for tech support (help with Xenia). + required: true + - label: If this issue occurs in a specific game, I've done analysis to locate the faulty subsystem of the emulator and a potential reason in it. + required: true + - label: I've checked if this issue hasn't already been reported. + required: true + - label: 'My device meets the minimum requirements: https://github.com/xenia-project/xenia/wiki/Quickstart#system-requirements' + required: true + - label: '(If building) I have read the building doc: https://github.com/xenia-project/xenia/blob/master/docs/building.md' + - type: textarea + id: problem + attributes: + label: Describe what's going wrong + validations: + required: true + - type: textarea + id: what-should-happen + attributes: + label: Describe what should happen + validations: + required: true + - type: textarea + id: callstack + attributes: + label: If applicable, provide a callstack here, especially for crashes + - type: textarea + id: logfile + attributes: + label: If applicable, upload a logfile and link it here diff --git a/.gitmodules b/.gitmodules index 280efab3a..7edb24d3c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -67,6 +67,12 @@ [submodule "third_party/premake-androidndk"] path = third_party/premake-androidndk url = https://github.com/Triang3l/premake-androidndk.git +[submodule "third_party/FidelityFX-CAS"] + path = third_party/FidelityFX-CAS + url = https://github.com/GPUOpen-Effects/FidelityFX-CAS.git +[submodule "third_party/FidelityFX-FSR"] + path = third_party/FidelityFX-FSR + url = https://github.com/GPUOpen-Effects/FidelityFX-FSR.git [submodule "third_party/glslang"] path = third_party/glslang url = https://github.com/KhronosGroup/glslang.git diff --git a/README.md b/README.md index 24599aed2..c0d0b5c8e 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ Discussing illegal activities will get you banned. ## Status -Buildbot | Status --------- | ------ -[Windows](https://ci.appveyor.com/project/benvanik/xenia/branch/master) | [![Build status](https://ci.appveyor.com/api/projects/status/ftqiy86kdfawyx3a/branch/master?svg=true)](https://ci.appveyor.com/project/benvanik/xenia/branch/master) +Buildbot | Status | Releases +-------- | ------ | -------- +[Windows](https://ci.appveyor.com/project/benvanik/xenia/branch/master) | [![Build status](https://ci.appveyor.com/api/projects/status/ftqiy86kdfawyx3a/branch/master?svg=true)](https://ci.appveyor.com/project/benvanik/xenia/branch/master) | [Latest](https://github.com/xenia-project/release-builds-windows/releases/latest) ◦ [All](https://github.com/xenia-project/release-builds-windows/releases) [Linux](https://cloud.drone.io/xenia-project/xenia) | [![Build status](https://cloud.drone.io/api/badges/xenia-project/xenia/status.svg)](https://cloud.drone.io/xenia-project/xenia) Quite a few real games run. Quite a few don't. @@ -61,7 +61,7 @@ Fixes and optimizations are always welcome (please!), but in addition to that there are some major work areas still untouched: * Help work through [missing functionality/bugs in games](https://github.com/xenia-project/xenia/labels/compat) -* Add input drivers for [third-party controllers](https://github.com/xenia-project/xenia/issues/1333) +* Reduce the size of Xenia's [huge log files](https://github.com/xenia-project/xenia/issues/1526) * Skilled with Linux? A strong contributor is needed to [help with porting](https://github.com/xenia-project/xenia/labels/platform-linux) See more projects [good for contributors](https://github.com/xenia-project/xenia/labels/good%20first%20issue). It's a good idea to ask on Discord and check the issues page before beginning work on diff --git a/android/android_studio_project/app/build.gradle b/android/android_studio_project/app/build.gradle index ff6acf7e2..ae753e1b2 100644 --- a/android/android_studio_project/app/build.gradle +++ b/android/android_studio_project/app/build.gradle @@ -4,7 +4,6 @@ plugins { android { compileSdkVersion 30 - buildToolsVersion '30.0.2' ndkVersion '23.0.7599858' defaultConfig { @@ -82,4 +81,8 @@ android { path file('../../../build/xenia.wks.Android.mk') } } +} + +dependencies { + implementation 'org.jetbrains:annotations:15.0' } \ No newline at end of file diff --git a/android/android_studio_project/app/src/main/AndroidManifest.xml b/android/android_studio_project/app/src/main/AndroidManifest.xml index 8f6d53cb0..25bf5a95f 100644 --- a/android/android_studio_project/app/src/main/AndroidManifest.xml +++ b/android/android_studio_project/app/src/main/AndroidManifest.xml @@ -29,7 +29,9 @@ android:supportsRtl="true" android:theme="@android:style/Theme.Material.Light"> - + diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/XeniaRuntimeException.java b/android/android_studio_project/app/src/main/java/jp/xenia/XeniaRuntimeException.java new file mode 100644 index 000000000..e5d324e78 --- /dev/null +++ b/android/android_studio_project/app/src/main/java/jp/xenia/XeniaRuntimeException.java @@ -0,0 +1,21 @@ +package jp.xenia; + +/** + * Base class for all unchecked exceptions thrown by the Xenia project components. + */ +public class XeniaRuntimeException extends RuntimeException { + public XeniaRuntimeException() { + } + + public XeniaRuntimeException(final String name) { + super(name); + } + + public XeniaRuntimeException(final String name, final Throwable cause) { + super(name, cause); + } + + public XeniaRuntimeException(final Exception cause) { + super(cause); + } +} diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java index a0dd36f0e..d03a07788 100644 --- a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java +++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java @@ -1,8 +1,18 @@ package jp.xenia.emulator; +import android.os.Bundle; + public class WindowDemoActivity extends WindowedAppActivity { @Override protected String getWindowedAppIdentifier() { return "xenia_ui_window_vulkan_demo"; } + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_window_demo); + setWindowSurfaceView(findViewById(R.id.window_demo_surface_view)); + } } diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowSurfaceView.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowSurfaceView.java new file mode 100644 index 000000000..23b014632 --- /dev/null +++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowSurfaceView.java @@ -0,0 +1,42 @@ +package jp.xenia.emulator; + +import android.content.Context; +import android.graphics.Canvas; +import android.util.AttributeSet; +import android.view.SurfaceView; + +public class WindowSurfaceView extends SurfaceView { + public WindowSurfaceView(final Context context) { + super(context); + // Native drawing is invoked from onDraw. + setWillNotDraw(false); + } + + public WindowSurfaceView(final Context context, final AttributeSet attrs) { + super(context, attrs); + setWillNotDraw(false); + } + + public WindowSurfaceView( + final Context context, final AttributeSet attrs, final int defStyleAttr) { + super(context, attrs, defStyleAttr); + setWillNotDraw(false); + } + + public WindowSurfaceView( + final Context context, final AttributeSet attrs, final int defStyleAttr, + final int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + setWillNotDraw(false); + } + + @Override + protected void onDraw(final Canvas canvas) { + final Context context = getContext(); + if (!(context instanceof WindowedAppActivity)) { + return; + } + final WindowedAppActivity activity = (WindowedAppActivity) context; + activity.onWindowSurfaceDraw(false); + } +} diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java index dd89881c3..073283529 100644 --- a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java +++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java @@ -3,43 +3,158 @@ package jp.xenia.emulator; import android.app.Activity; import android.content.res.AssetManager; import android.os.Bundle; -import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.View; + +import org.jetbrains.annotations.Nullable; + +import jp.xenia.XeniaRuntimeException; public abstract class WindowedAppActivity extends Activity { - private static final String TAG = "WindowedAppActivity"; - static { // TODO(Triang3l): Move all demos to libxenia.so. System.loadLibrary("xenia-ui-window-vulkan-demo"); } - private long mAppContext; + private final WindowSurfaceOnLayoutChangeListener mWindowSurfaceOnLayoutChangeListener = + new WindowSurfaceOnLayoutChangeListener(); + private final WindowSurfaceHolderCallback mWindowSurfaceHolderCallback = + new WindowSurfaceHolderCallback(); - private native long initializeWindowedAppOnCreateNative( + // May be 0 while destroying (mainly while the superclass is). + private long mAppContext = 0; + + @Nullable + private WindowSurfaceView mWindowSurfaceView = null; + + private native long initializeWindowedAppOnCreate( String windowedAppIdentifier, AssetManager assetManager); private native void onDestroyNative(long appContext); + private native void onWindowSurfaceLayoutChange( + long appContext, int left, int top, int right, int bottom); + + private native void onWindowSurfaceChanged(long appContext, Surface windowSurface); + + private native void paintWindow(long appContext, boolean forcePaint); + protected abstract String getWindowedAppIdentifier(); + protected void setWindowSurfaceView(@Nullable final WindowSurfaceView windowSurfaceView) { + if (mWindowSurfaceView == windowSurfaceView) { + return; + } + + // Detach from the old surface. + if (mWindowSurfaceView != null) { + mWindowSurfaceView.getHolder().removeCallback(mWindowSurfaceHolderCallback); + mWindowSurfaceView.removeOnLayoutChangeListener(mWindowSurfaceOnLayoutChangeListener); + mWindowSurfaceView = null; + if (mAppContext != 0) { + onWindowSurfaceChanged(mAppContext, null); + } + } + + if (windowSurfaceView == null) { + return; + } + + mWindowSurfaceView = windowSurfaceView; + // The native window code assumes that, when the surface exists, it covers the entire + // window. + // FIXME(Triang3l): This doesn't work if the layout has already been performed. + mWindowSurfaceView.addOnLayoutChangeListener(mWindowSurfaceOnLayoutChangeListener); + final SurfaceHolder windowSurfaceHolder = mWindowSurfaceView.getHolder(); + windowSurfaceHolder.addCallback(mWindowSurfaceHolderCallback); + // If setting after the creation of the surface. + if (mAppContext != 0) { + final Surface windowSurface = windowSurfaceHolder.getSurface(); + if (windowSurface != null) { + onWindowSurfaceChanged(mAppContext, windowSurface); + } + } + } + + public void onWindowSurfaceDraw(final boolean forcePaint) { + if (mAppContext == 0) { + return; + } + paintWindow(mAppContext, forcePaint); + } + + // Used from the native WindowedAppContext. May be called from non-UI threads. + protected void postInvalidateWindowSurface() { + if (mWindowSurfaceView == null) { + return; + } + mWindowSurfaceView.postInvalidate(); + } + @Override - protected void onCreate(Bundle savedInstanceState) { + protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mAppContext = initializeWindowedAppOnCreateNative(getWindowedAppIdentifier(), getAssets()); + final String windowedAppIdentifier = getWindowedAppIdentifier(); + mAppContext = initializeWindowedAppOnCreate(windowedAppIdentifier, getAssets()); if (mAppContext == 0) { - Log.e(TAG, "Error initializing the windowed app"); finish(); - return; + throw new XeniaRuntimeException( + "Error initializing the windowed app " + windowedAppIdentifier); } } @Override protected void onDestroy() { + setWindowSurfaceView(null); if (mAppContext != 0) { onDestroyNative(mAppContext); } mAppContext = 0; super.onDestroy(); } + + private class WindowSurfaceOnLayoutChangeListener implements View.OnLayoutChangeListener { + @Override + public void onLayoutChange( + final View v, final int left, final int top, final int right, final int bottom, + final int oldLeft, final int oldTop, final int oldRight, final int oldBottom) { + if (mAppContext != 0) { + onWindowSurfaceLayoutChange(mAppContext, left, top, right, bottom); + } + } + } + + private class WindowSurfaceHolderCallback implements SurfaceHolder.Callback2 { + @Override + public void surfaceCreated(final SurfaceHolder holder) { + if (mAppContext == 0) { + return; + } + onWindowSurfaceChanged(mAppContext, holder.getSurface()); + } + + @Override + public void surfaceChanged( + final SurfaceHolder holder, final int format, final int width, final int height) { + if (mAppContext == 0) { + return; + } + onWindowSurfaceChanged(mAppContext, holder.getSurface()); + } + + @Override + public void surfaceDestroyed(final SurfaceHolder holder) { + if (mAppContext == 0) { + return; + } + onWindowSurfaceChanged(mAppContext, null); + } + + @Override + public void surfaceRedrawNeeded(final SurfaceHolder holder) { + onWindowSurfaceDraw(true); + } + } } diff --git a/android/android_studio_project/app/src/main/res/layout/activity_window_demo.xml b/android/android_studio_project/app/src/main/res/layout/activity_window_demo.xml index 79f49f81a..3bbd1211b 100644 --- a/android/android_studio_project/app/src/main/res/layout/activity_window_demo.xml +++ b/android/android_studio_project/app/src/main/res/layout/activity_window_demo.xml @@ -1,8 +1,7 @@ - - - \ No newline at end of file + tools:context="jp.xenia.emulator.WindowDemoActivity" /> diff --git a/android/android_studio_project/app/src/main/res/values/strings.xml b/android/android_studio_project/app/src/main/res/values/strings.xml index 6379b7bcb..ed3f21a79 100644 --- a/android/android_studio_project/app/src/main/res/values/strings.xml +++ b/android/android_studio_project/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ Xenia + Xenia Window Demo \ No newline at end of file diff --git a/android/android_studio_project/build.gradle b/android/android_studio_project/build.gradle index 971fd1b37..fee7fd669 100644 --- a/android/android_studio_project/build.gradle +++ b/android/android_studio_project/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.3' + classpath 'com.android.tools.build:gradle:7.1.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index 62d288f19..a4dbb8786 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -2,13 +2,20 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/app/emulator_window.h" +#include +#include +#include +#include +#include +#include + #include "third_party/fmt/include/fmt/format.h" #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" @@ -20,11 +27,17 @@ #include "xenia/base/profiling.h" #include "xenia/base/system.h" #include "xenia/base/threading.h" +#include "xenia/cpu/processor.h" #include "xenia/emulator.h" +#include "xenia/gpu/command_processor.h" #include "xenia/gpu/graphics_system.h" #include "xenia/ui/file_picker.h" +#include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/virtual_key.h" // Autogenerated by `xb premake`. @@ -32,13 +45,91 @@ DECLARE_bool(debug); +DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.", + "Display"); + +DEFINE_string( + postprocess_antialiasing, "", + "Post-processing anti-aliasing effect to apply to the image output of the " + "game.\n" + "Using post-process anti-aliasing is heavily recommended when AMD " + "FidelityFX Contrast Adaptive Sharpening or Super Resolution 1.0 is " + "active.\n" + "Use: [none, fxaa, fxaa_extreme]\n" + " none (or any value not listed here):\n" + " Don't alter the original image.\n" + " fxaa:\n" + " NVIDIA Fast Approximate Anti-Aliasing 3.11, normal quality preset (12)." + "\n" + " fxaa_extreme:\n" + " NVIDIA Fast Approximate Anti-Aliasing 3.11, extreme quality preset " + "(39).", + "Display"); +DEFINE_string( + postprocess_scaling_and_sharpening, "", + "Post-processing effect to use for resampling and/or sharpening of the " + "final display output.\n" + "Use: [bilinear, cas, fsr]\n" + " bilinear (or any value not listed here):\n" + " Original image at 1:1, simple bilinear stretching for resampling.\n" + " cas:\n" + " Use AMD FidelityFX Contrast Adaptive Sharpening (CAS) for sharpening " + "at scaling factors of up to 2x2, with additional bilinear stretching for " + "larger factors.\n" + " fsr:\n" + " Use AMD FidelityFX Super Resolution 1.0 (FSR) for highest-quality " + "upscaling, or AMD FidelityFX Contrast Adaptive Sharpening for sharpening " + "while not scaling or downsampling.\n" + " For scaling by factors of more than 2x2, multiple FSR passes are done.", + "Display"); +DEFINE_double( + postprocess_ffx_cas_additional_sharpness, + xe::ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessDefault, + "Additional sharpness for AMD FidelityFX Contrast Adaptive Sharpening " + "(CAS), from 0 to 1.\n" + "Higher is sharper.", + "Display"); +DEFINE_uint32( + postprocess_ffx_fsr_max_upsampling_passes, + xe::ui::Presenter::GuestOutputPaintConfig::kFsrMaxUpscalingPassesMax, + "Maximum number of upsampling passes performed in AMD FidelityFX Super " + "Resolution 1.0 (FSR) before falling back to bilinear stretching after the " + "final pass.\n" + "Each pass upscales only to up to 2x2 the previous size. If the game " + "outputs a 1280x720 image, 1 pass will upscale it to up to 2560x1440 " + "(below 4K), after 2 passes it will be upscaled to a maximum of 5120x2880 " + "(including 3840x2160 for 4K), and so on.\n" + "This variable has no effect if the display resolution isn't very high, " + "but may be reduced on resolutions like 4K or 8K in case the performance " + "impact of multiple FSR upsampling passes is too high, or if softer edges " + "are desired.\n" + "The default value is the maximum internally supported by Xenia.", + "Display"); +DEFINE_double( + postprocess_ffx_fsr_sharpness_reduction, + xe::ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionDefault, + "Sharpness reduction for AMD FidelityFX Super Resolution 1.0 (FSR), in " + "stops.\n" + "Lower is sharper.", + "Display"); +// Dithering to 8bpc is enabled by default since the effect is minor, only +// effects what can't be shown normally by host displays, and nothing is changed +// by it for 8bpc source without resampling. +DEFINE_bool( + postprocess_dither, true, + "Dither the final image output from the internal precision to 8 bits per " + "channel so gradients are smoother.\n" + "On a 10bpc display, the lower 2 bits will still be kept, but noise will " + "be added to them - disabling may be recommended for 10bpc, but it " + "depends on the 10bpc displaying capabilities of the actual display used.", + "Display"); + namespace xe { namespace app { using xe::ui::FileDropEvent; using xe::ui::KeyEvent; using xe::ui::MenuItem; -using xe::ui::MouseEvent; using xe::ui::UIEvent; const std::string kBaseTitle = "Xenia"; @@ -47,7 +138,12 @@ EmulatorWindow::EmulatorWindow(Emulator* emulator, ui::WindowedAppContext& app_context) : emulator_(emulator), app_context_(app_context), - window_(ui::Window::Create(app_context, kBaseTitle)) { + window_listener_(*this), + window_(ui::Window::Create(app_context, kBaseTitle, 1280, 720)), + imgui_drawer_( + std::make_unique(window_.get(), kZOrderImGui)), + display_config_game_config_load_callback_( + new DisplayConfigGameConfigLoadCallback(*emulator, *this)) { base_title_ = kBaseTitle + #ifdef DEBUG #if _NO_DEBUG_HEAP == 1 @@ -76,107 +172,331 @@ std::unique_ptr EmulatorWindow::Create( return emulator_window; } -bool EmulatorWindow::Initialize() { - if (!window_->Initialize()) { - XELOGE("Failed to initialize platform window"); - return false; +EmulatorWindow::~EmulatorWindow() { + // Notify the ImGui drawer that the immediate drawer is being destroyed. + ShutdownGraphicsSystemPresenterPainting(); +} + +ui::Presenter* EmulatorWindow::GetGraphicsSystemPresenter() const { + gpu::GraphicsSystem* graphics_system = emulator_->graphics_system(); + return graphics_system ? graphics_system->presenter() : nullptr; +} + +void EmulatorWindow::SetupGraphicsSystemPresenterPainting() { + ShutdownGraphicsSystemPresenterPainting(); + + if (!window_) { + return; } - UpdateTitle(); + ui::Presenter* presenter = GetGraphicsSystemPresenter(); + if (!presenter) { + return; + } - window_->on_closed.AddListener( - [this](UIEvent* e) { app_context_.QuitFromUIThread(); }); + ApplyDisplayConfigForCvars(); - window_->on_file_drop.AddListener( - [this](FileDropEvent* e) { FileDrop(e->filename()); }); + window_->SetPresenter(presenter); - window_->on_key_down.AddListener([this](KeyEvent* e) { - bool handled = true; - switch (e->virtual_key()) { - case ui::VirtualKey::kO: { - if (e->is_ctrl_pressed()) { - FileOpen(); - } - } break; - case ui::VirtualKey::kMultiply: { - CpuTimeScalarReset(); - } break; - case ui::VirtualKey::kSubtract: { - CpuTimeScalarSetHalf(); - } break; - case ui::VirtualKey::kAdd: { - CpuTimeScalarSetDouble(); - } break; + immediate_drawer_ = + emulator_->graphics_system()->provider()->CreateImmediateDrawer(); + if (immediate_drawer_) { + immediate_drawer_->SetPresenter(presenter); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter, + immediate_drawer_.get()); + Profiler::SetUserIO(kZOrderProfiler, window_.get(), presenter, + immediate_drawer_.get()); + } +} - case ui::VirtualKey::kF3: { - Profiler::ToggleDisplay(); - } break; +void EmulatorWindow::ShutdownGraphicsSystemPresenterPainting() { + Profiler::SetUserIO(kZOrderProfiler, window_.get(), nullptr, nullptr); + imgui_drawer_->SetPresenterAndImmediateDrawer(nullptr, nullptr); + immediate_drawer_.reset(); + if (window_) { + window_->SetPresenter(nullptr); + } +} - case ui::VirtualKey::kF4: { - GpuTraceFrame(); - } break; - case ui::VirtualKey::kF5: { - GpuClearCaches(); - } break; - case ui::VirtualKey::kF7: { - // Save to file - // TODO: Choose path based on user input, or from options - // TODO: Spawn a new thread to do this. - emulator()->SaveToFile("test.sav"); - } break; - case ui::VirtualKey::kF8: { - // Restore from file - // TODO: Choose path from user - // TODO: Spawn a new thread to do this. - emulator()->RestoreFromFile("test.sav"); - } break; - case ui::VirtualKey::kF11: { - ToggleFullscreen(); - } break; - case ui::VirtualKey::kEscape: { - // Allow users to escape fullscreen (but not enter it). - if (window_->is_fullscreen()) { - window_->ToggleFullscreen(false); - } else { - handled = false; - } - } break; +void EmulatorWindow::OnEmulatorInitialized() { + emulator_initialized_ = true; + window_->SetMainMenuEnabled(true); + // When the user can see that the emulator isn't initializing anymore (the + // menu isn't disabled), enter fullscreen if requested. + if (cvars::fullscreen) { + window_->SetFullscreen(true); + } +} - case ui::VirtualKey::kPause: { - CpuBreakIntoDebugger(); - } break; - case ui::VirtualKey::kCancel: { - CpuBreakIntoHostDebugger(); - } break; +void EmulatorWindow::EmulatorWindowListener::OnClosing(ui::UIEvent& e) { + emulator_window_.app_context_.QuitFromUIThread(); +} - case ui::VirtualKey::kF1: { - ShowHelpWebsite(); - } break; +void EmulatorWindow::EmulatorWindowListener::OnFileDrop(ui::FileDropEvent& e) { + emulator_window_.FileDrop(e.filename()); +} - case ui::VirtualKey::kF2: { - ShowCommitID(); - } break; +void EmulatorWindow::EmulatorWindowListener::OnKeyDown(ui::KeyEvent& e) { + emulator_window_.OnKeyDown(e); +} - default: { - handled = false; - } break; - } - e->set_handled(handled); - }); +void EmulatorWindow::DisplayConfigGameConfigLoadCallback::PostGameConfigLoad() { + emulator_window_.ApplyDisplayConfigForCvars(); +} - window_->on_mouse_move.AddListener([this](MouseEvent* e) { - if (window_->is_fullscreen() && (e->dx() > 2 || e->dy() > 2)) { - if (!window_->is_cursor_visible()) { - window_->set_cursor_visible(true); +void EmulatorWindow::DisplayConfigDialog::OnDraw(ImGuiIO& io) { + gpu::GraphicsSystem* graphics_system = + emulator_window_.emulator_->graphics_system(); + if (!graphics_system) { + return; + } + + // In the top-left corner so it's close to the menu bar from where it was + // opened. + // Origin Y coordinate 20 was taken from the Dear ImGui demo. + ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(20, 20), ImGuiCond_FirstUseEver); + // Alpha from Dear ImGui tooltips (0.35 from the overlay provides too low + // visibility). Translucent so some effect of the changes can still be seen + // through it. + ImGui::SetNextWindowBgAlpha(0.6f); + bool dialog_open = true; + if (!ImGui::Begin("Post-processing", &dialog_open, + ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_HorizontalScrollbar)) { + ImGui::End(); + return; + } + // Even if the close button has been pressed, still paint everything not to + // have one frame with an empty window. + + // Prevent user confusion which has been reported multiple times. + ImGui::TextUnformatted("All effects can be used on GPUs of any brand."); + ImGui::Spacing(); + + gpu::CommandProcessor* command_processor = + graphics_system->command_processor(); + if (command_processor) { + if (ImGui::TreeNodeEx( + "Anti-aliasing", + ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_DefaultOpen)) { + gpu::CommandProcessor::SwapPostEffect current_swap_post_effect = + command_processor->GetDesiredSwapPostEffect(); + int new_swap_post_effect_index = int(current_swap_post_effect); + ImGui::RadioButton("None", &new_swap_post_effect_index, + int(gpu::CommandProcessor::SwapPostEffect::kNone)); + ImGui::RadioButton( + "NVIDIA Fast Approximate Anti-Aliasing 3.11 (FXAA), normal quality", + &new_swap_post_effect_index, + int(gpu::CommandProcessor::SwapPostEffect::kFxaa)); + ImGui::RadioButton( + "NVIDIA Fast Approximate Anti-Aliasing 3.11 (FXAA), extreme quality", + &new_swap_post_effect_index, + int(gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme)); + gpu::CommandProcessor::SwapPostEffect new_swap_post_effect = + gpu::CommandProcessor::SwapPostEffect(new_swap_post_effect_index); + if (current_swap_post_effect != new_swap_post_effect) { + command_processor->SetDesiredSwapPostEffect(new_swap_post_effect); } - cursor_hide_time_ = Clock::QueryHostSystemTime() + 30000000; + // Override the values in the cvars to save them to the config at exit if + // the user has set them to anything new. + if (GetSwapPostEffectForCvarValue(cvars::postprocess_antialiasing) != + new_swap_post_effect) { + OVERRIDE_string(postprocess_antialiasing, + GetCvarValueForSwapPostEffect(new_swap_post_effect)); + } + + ImGui::TreePop(); + } + } + + ui::Presenter* presenter = graphics_system->presenter(); + if (presenter) { + const ui::Presenter::GuestOutputPaintConfig& current_presenter_config = + presenter->GetGuestOutputPaintConfigFromUIThread(); + ui::Presenter::GuestOutputPaintConfig new_presenter_config = + current_presenter_config; + + if (ImGui::TreeNodeEx( + "Resampling and sharpening", + ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_DefaultOpen)) { + // Filtering effect. + int new_effect_index = int(new_presenter_config.GetEffect()); + ImGui::RadioButton( + "None / bilinear", &new_effect_index, + int(ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear)); + ImGui::RadioButton( + "AMD FidelityFX Contrast Adaptive Sharpening (CAS)", + &new_effect_index, + int(ui::Presenter::GuestOutputPaintConfig::Effect::kCas)); + ImGui::RadioButton( + "AMD FidelityFX Super Resolution 1.0 (FSR)", &new_effect_index, + int(ui::Presenter::GuestOutputPaintConfig::Effect::kFsr)); + new_presenter_config.SetEffect( + ui::Presenter::GuestOutputPaintConfig::Effect(new_effect_index)); + + // effect_description must be one complete, but short enough, sentence per + // line, as TextWrapped doesn't work correctly in auto-resizing windows + // (in the initial frames, the window becomes extremely tall, and widgets + // added after the wrapped text have no effect on the width of the text). + const char* effect_description = nullptr; + switch (new_presenter_config.GetEffect()) { + case ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear: + effect_description = + "Simple bilinear filtering is done if resampling is needed.\n" + "Otherwise, only anti-aliasing is done if enabled, or displaying " + "as is."; + break; + case ui::Presenter::GuestOutputPaintConfig::Effect::kCas: + effect_description = + "Sharpening and resampling to up to 2x2 to improve the fidelity " + "of details.\n" + "For scaling by more than 2x2, bilinear stretching is done " + "afterwards."; + break; + case ui::Presenter::GuestOutputPaintConfig::Effect::kFsr: + effect_description = + "High-quality edge-preserving upscaling to arbitrary target " + "resolutions.\n" + "For scaling by more than 2x2, multiple upsampling passes are " + "done.\n" + "If not upscaling, Contrast Adaptive Sharpening (CAS) is used " + "instead."; + break; + } + if (effect_description) { + ImGui::TextUnformatted(effect_description); + } + + if (new_presenter_config.GetEffect() == + ui::Presenter::GuestOutputPaintConfig::Effect::kCas || + new_presenter_config.GetEffect() == + ui::Presenter::GuestOutputPaintConfig::Effect::kFsr) { + if (effect_description) { + ImGui::Spacing(); + } + + ImGui::TextUnformatted( + "FXAA is highly recommended when using CAS or FSR."); + + ImGui::Spacing(); + + // 2 decimal places is more or less enough precision for the sharpness + // given the minor visual effect of small changes, the width of the + // slider, and readability convenience (2 decimal places is like an + // integer percentage). However, because Dear ImGui parses the string + // representation of the number and snaps the value to it internally, + // 2 decimal places actually offer less precision than the slider itself + // does. This is especially prominent in the low range of the non-linear + // FSR sharpness reduction slider. 3 decimal places are optimal in this + // case. + + if (new_presenter_config.GetEffect() == + ui::Presenter::GuestOutputPaintConfig::Effect::kFsr) { + float fsr_sharpness_reduction = + new_presenter_config.GetFsrSharpnessReduction(); + ImGui::TextUnformatted( + "FSR sharpness reduction when upscaling (lower is sharper):"); + // Power 2.0 as the reduction is in stops, used in exp2. + ImGui::SliderFloat( + "##FSRSharpnessReduction", &fsr_sharpness_reduction, + ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionMin, + ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionMax, + "%.3f stops", 2.0f); + ImGui::SameLine(); + if (ImGui::Button("Reset##ResetFSRSharpnessReduction")) { + fsr_sharpness_reduction = ui::Presenter::GuestOutputPaintConfig :: + kFsrSharpnessReductionDefault; + } + new_presenter_config.SetFsrSharpnessReduction( + fsr_sharpness_reduction); + } + + float cas_additional_sharpness = + new_presenter_config.GetCasAdditionalSharpness(); + ImGui::TextUnformatted( + new_presenter_config.GetEffect() == + ui::Presenter::GuestOutputPaintConfig::Effect::kFsr + ? "CAS additional sharpness when not upscaling (higher is " + "sharper):" + : "CAS additional sharpness (higher is sharper):"); + ImGui::SliderFloat( + "##CASAdditionalSharpness", &cas_additional_sharpness, + ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessMin, + ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessMax, + "%.3f"); + ImGui::SameLine(); + if (ImGui::Button("Reset##ResetCASAdditionalSharpness")) { + cas_additional_sharpness = ui::Presenter::GuestOutputPaintConfig :: + kCasAdditionalSharpnessDefault; + } + new_presenter_config.SetCasAdditionalSharpness( + cas_additional_sharpness); + + // There's no need to expose the setting for the maximum number of FSR + // EASU passes as it's largely meaningless if the user doesn't have a + // very high-resolution monitor compared to the original image size as + // most of the values of the slider will have no effect, and that's just + // very fine-grained performance control for a fixed-overhead pass only + // for huge screen resolutions. + } + + ImGui::TreePop(); } - e->set_handled(false); - }); + if (ImGui::TreeNodeEx("Dithering", ImGuiTreeNodeFlags_Framed | + ImGuiTreeNodeFlags_DefaultOpen)) { + bool dither = current_presenter_config.GetDither(); + ImGui::Checkbox( + "Dither the final output to 8bpc to make gradients smoother", + &dither); + new_presenter_config.SetDither(dither); - window_->on_paint.AddListener([this](UIEvent* e) { CheckHideCursor(); }); + ImGui::TreePop(); + } + + presenter->SetGuestOutputPaintConfigFromUIThread(new_presenter_config); + + // Override the values in the cvars to save them to the config at exit if + // the user has set them to anything new. + ui::Presenter::GuestOutputPaintConfig cvars_presenter_config = + GetGuestOutputPaintConfigForCvars(); + if (cvars_presenter_config.GetEffect() != + new_presenter_config.GetEffect()) { + OVERRIDE_string(postprocess_scaling_and_sharpening, + GetCvarValueForGuestOutputPaintEffect( + new_presenter_config.GetEffect())); + } + if (cvars_presenter_config.GetCasAdditionalSharpness() != + new_presenter_config.GetCasAdditionalSharpness()) { + OVERRIDE_double(postprocess_ffx_cas_additional_sharpness, + new_presenter_config.GetCasAdditionalSharpness()); + } + if (cvars_presenter_config.GetFsrSharpnessReduction() != + new_presenter_config.GetFsrSharpnessReduction()) { + OVERRIDE_double(postprocess_ffx_fsr_sharpness_reduction, + new_presenter_config.GetFsrSharpnessReduction()); + } + if (cvars_presenter_config.GetDither() != + new_presenter_config.GetDither()) { + OVERRIDE_bool(postprocess_dither, new_presenter_config.GetDither()); + } + } + + ImGui::End(); + + if (!dialog_open) { + emulator_window_.ToggleDisplayConfigDialog(); + // `this` might have been destroyed by ToggleDisplayConfigDialog. + return; + } +} + +bool EmulatorWindow::Initialize() { + window_->AddListener(&window_listener_); + window_->AddInputListener(&window_listener_, kZOrderEmulatorWindowInput); // Main menu. // FIXME: This code is really messy. @@ -186,17 +506,19 @@ bool EmulatorWindow::Initialize() { file_menu->AddChild( MenuItem::Create(MenuItem::Type::kString, "&Open...", "Ctrl+O", std::bind(&EmulatorWindow::FileOpen, this))); +#ifdef DEBUG file_menu->AddChild( MenuItem::Create(MenuItem::Type::kString, "Close", std::bind(&EmulatorWindow::FileClose, this))); +#endif // #ifdef DEBUG file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); file_menu->AddChild(MenuItem::Create( MenuItem::Type::kString, "Show content directory...", std::bind(&EmulatorWindow::ShowContentDirectory, this))); file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "E&xit", - "Alt+F4", - [this]() { window_->Close(); })); + file_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "E&xit", "Alt+F4", + [this]() { window_->RequestClose(); })); } main_menu->AddChild(std::move(file_menu)); @@ -249,21 +571,35 @@ bool EmulatorWindow::Initialize() { } main_menu->AddChild(std::move(gpu_menu)); - // Window menu. - auto window_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Window"); + // Display menu. + auto display_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Display"); { - window_menu->AddChild( + display_menu->AddChild(MenuItem::Create( + MenuItem::Type::kString, "&Post-processing settings", "F6", + std::bind(&EmulatorWindow::ToggleDisplayConfigDialog, this))); + } + display_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); + { + display_menu->AddChild( MenuItem::Create(MenuItem::Type::kString, "&Fullscreen", "F11", std::bind(&EmulatorWindow::ToggleFullscreen, this))); } - main_menu->AddChild(std::move(window_menu)); + main_menu->AddChild(std::move(display_menu)); // Help menu. auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Help"); { help_menu->AddChild( - MenuItem::Create(MenuItem::Type::kString, "Build commit on GitHub...", - "F2", std::bind(&EmulatorWindow::ShowCommitID, this))); + MenuItem::Create(MenuItem::Type::kString, "FA&Q...", "F1", + std::bind(&EmulatorWindow::ShowFAQ, this))); + help_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); + help_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "Game &compatibility...", + std::bind(&EmulatorWindow::ShowCompatibility, this))); + help_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); + help_menu->AddChild(MenuItem::Create( + MenuItem::Type::kString, "Build commit on GitHub...", "F2", + std::bind(&EmulatorWindow::ShowBuildCommit, this))); help_menu->AddChild(MenuItem::Create( MenuItem::Type::kString, "Recent changes on GitHub...", [this]() { LaunchWebBrowser( @@ -271,25 +607,202 @@ bool EmulatorWindow::Initialize() { "..." XE_BUILD_BRANCH); })); help_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); - help_menu->AddChild( - MenuItem::Create(MenuItem::Type::kString, "&Website...", "F1", - std::bind(&EmulatorWindow::ShowHelpWebsite, this))); help_menu->AddChild(MenuItem::Create( MenuItem::Type::kString, "&About...", [this]() { LaunchWebBrowser("https://xenia.jp/about/"); })); } main_menu->AddChild(std::move(help_menu)); - window_->set_main_menu(std::move(main_menu)); + window_->SetMainMenu(std::move(main_menu)); - window_->Resize(1280, 720); + window_->SetMainMenuEnabled(false); - window_->DisableMainMenu(); + UpdateTitle(); + + if (!window_->Open()) { + XELOGE("Failed to open the platform window"); + return false; + } + + Profiler::SetUserIO(kZOrderProfiler, window_.get(), nullptr, nullptr); return true; } +const char* EmulatorWindow::GetCvarValueForSwapPostEffect( + gpu::CommandProcessor::SwapPostEffect effect) { + switch (effect) { + case gpu::CommandProcessor::SwapPostEffect::kFxaa: + return "fxaa"; + case gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme: + return "fxaa_extreme"; + default: + return ""; + } +} + +gpu::CommandProcessor::SwapPostEffect +EmulatorWindow::GetSwapPostEffectForCvarValue(const std::string& cvar_value) { + if (cvar_value == GetCvarValueForSwapPostEffect( + gpu::CommandProcessor::SwapPostEffect::kFxaa)) { + return gpu::CommandProcessor::SwapPostEffect::kFxaa; + } + if (cvar_value == GetCvarValueForSwapPostEffect( + gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme)) { + return gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme; + } + return gpu::CommandProcessor::SwapPostEffect::kNone; +} + +const char* EmulatorWindow::GetCvarValueForGuestOutputPaintEffect( + ui::Presenter::GuestOutputPaintConfig::Effect effect) { + switch (effect) { + case ui::Presenter::GuestOutputPaintConfig::Effect::kCas: + return "cas"; + case ui::Presenter::GuestOutputPaintConfig::Effect::kFsr: + return "fsr"; + default: + return ""; + } +} + +ui::Presenter::GuestOutputPaintConfig::Effect +EmulatorWindow::GetGuestOutputPaintEffectForCvarValue( + const std::string& cvar_value) { + if (cvar_value == GetCvarValueForGuestOutputPaintEffect( + ui::Presenter::GuestOutputPaintConfig::Effect::kCas)) { + return ui::Presenter::GuestOutputPaintConfig::Effect::kCas; + } + if (cvar_value == GetCvarValueForGuestOutputPaintEffect( + ui::Presenter::GuestOutputPaintConfig::Effect::kFsr)) { + return ui::Presenter::GuestOutputPaintConfig::Effect::kFsr; + } + return ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear; +} + +ui::Presenter::GuestOutputPaintConfig +EmulatorWindow::GetGuestOutputPaintConfigForCvars() { + ui::Presenter::GuestOutputPaintConfig paint_config; + paint_config.SetEffect(GetGuestOutputPaintEffectForCvarValue( + cvars::postprocess_scaling_and_sharpening)); + paint_config.SetCasAdditionalSharpness( + float(cvars::postprocess_ffx_cas_additional_sharpness)); + paint_config.SetFsrMaxUpsamplingPasses( + cvars::postprocess_ffx_fsr_max_upsampling_passes); + paint_config.SetFsrSharpnessReduction( + float(cvars::postprocess_ffx_fsr_sharpness_reduction)); + paint_config.SetDither(cvars::postprocess_dither); + return paint_config; +} + +void EmulatorWindow::ApplyDisplayConfigForCvars() { + gpu::GraphicsSystem* graphics_system = emulator_->graphics_system(); + if (!graphics_system) { + return; + } + + gpu::CommandProcessor* command_processor = + graphics_system->command_processor(); + if (command_processor) { + command_processor->SetDesiredSwapPostEffect( + GetSwapPostEffectForCvarValue(cvars::postprocess_antialiasing)); + } + + ui::Presenter* presenter = graphics_system->presenter(); + if (presenter) { + presenter->SetGuestOutputPaintConfigFromUIThread( + GetGuestOutputPaintConfigForCvars()); + } +} + +void EmulatorWindow::OnKeyDown(ui::KeyEvent& e) { + if (!emulator_initialized_) { + return; + } + + switch (e.virtual_key()) { + case ui::VirtualKey::kO: { + if (!e.is_ctrl_pressed()) { + return; + } + FileOpen(); + } break; + case ui::VirtualKey::kMultiply: { + CpuTimeScalarReset(); + } break; + case ui::VirtualKey::kSubtract: { + CpuTimeScalarSetHalf(); + } break; + case ui::VirtualKey::kAdd: { + CpuTimeScalarSetDouble(); + } break; + + case ui::VirtualKey::kF3: { + Profiler::ToggleDisplay(); + } break; + + case ui::VirtualKey::kF4: { + GpuTraceFrame(); + } break; + case ui::VirtualKey::kF5: { + GpuClearCaches(); + } break; + + case ui::VirtualKey::kF6: { + ToggleDisplayConfigDialog(); + } break; + case ui::VirtualKey::kF11: { + ToggleFullscreen(); + } break; + case ui::VirtualKey::kEscape: { + // Allow users to escape fullscreen (but not enter it). + if (!window_->IsFullscreen()) { + return; + } + SetFullscreen(false); + } break; + +#ifdef DEBUG + case ui::VirtualKey::kF7: { + // Save to file + // TODO: Choose path based on user input, or from options + // TODO: Spawn a new thread to do this. + emulator()->SaveToFile("test.sav"); + } break; + case ui::VirtualKey::kF8: { + // Restore from file + // TODO: Choose path from user + // TODO: Spawn a new thread to do this. + emulator()->RestoreFromFile("test.sav"); + } break; +#endif // #ifdef DEBUG + + case ui::VirtualKey::kPause: { + CpuBreakIntoDebugger(); + } break; + case ui::VirtualKey::kCancel: { + CpuBreakIntoHostDebugger(); + } break; + + case ui::VirtualKey::kF1: { + ShowFAQ(); + } break; + + case ui::VirtualKey::kF2: { + ShowBuildCommit(); + } break; + + default: + return; + } + + e.set_handled(true); +} + void EmulatorWindow::FileDrop(const std::filesystem::path& filename) { + if (!emulator_initialized_) { + return; + } auto result = emulator_->LaunchPath(filename); if (XFAILED(result)) { // TODO: Display a message box. @@ -312,7 +825,7 @@ void EmulatorWindow::FileOpen() { //{"Content Package (*.xcp)", "*.xcp" }, {"All Files (*.*)", "*.*"}, }); - if (file_picker->Show(window_->native_handle())) { + if (file_picker->Show(window_.get())) { auto selected_files = file_picker->selected_files(); if (!selected_files.empty()) { path = selected_files[0]; @@ -357,17 +870,6 @@ void EmulatorWindow::ShowContentDirectory() { LaunchFileExplorer(target_path); } -void EmulatorWindow::CheckHideCursor() { - if (!window_->is_fullscreen()) { - // Only hide when fullscreen. - return; - } - - if (Clock::QueryHostSystemTime() > cursor_hide_time_) { - window_->set_cursor_visible(false); - } -} - void EmulatorWindow::CpuTimeScalarReset() { Clock::set_guest_time_scalar(1.0); UpdateTitle(); @@ -385,7 +887,7 @@ void EmulatorWindow::CpuTimeScalarSetDouble() { void EmulatorWindow::CpuBreakIntoDebugger() { if (!cvars::debug) { - xe::ui::ImGuiDialog::ShowMessageBox(window_.get(), "Xenia Debugger", + xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(), "Xenia Debugger", "Xenia must be launched with the " "--debug flag in order to enable " "debugging."); @@ -411,19 +913,48 @@ void EmulatorWindow::GpuClearCaches() { emulator()->graphics_system()->ClearCaches(); } -void EmulatorWindow::ToggleFullscreen() { - window_->ToggleFullscreen(!window_->is_fullscreen()); +void EmulatorWindow::SetFullscreen(bool fullscreen) { + if (window_->IsFullscreen() == fullscreen) { + return; + } + window_->SetFullscreen(fullscreen); + window_->SetCursorVisibility(fullscreen + ? ui::Window::CursorVisibility::kAutoHidden + : ui::Window::CursorVisibility::kVisible); +} - // Hide the cursor after a second if we're going fullscreen - cursor_hide_time_ = Clock::QueryHostSystemTime() + 30000000; - if (!window_->is_fullscreen()) { - window_->set_cursor_visible(true); +void EmulatorWindow::ToggleFullscreen() { + SetFullscreen(!window_->IsFullscreen()); +} + +void EmulatorWindow::ToggleDisplayConfigDialog() { + if (!display_config_dialog_) { + display_config_dialog_ = std::unique_ptr( + new DisplayConfigDialog(imgui_drawer_.get(), *this)); + } else { + display_config_dialog_.reset(); } } -void EmulatorWindow::ShowHelpWebsite() { LaunchWebBrowser("https://xenia.jp"); } +void EmulatorWindow::ShowCompatibility() { + const std::string_view base_url = + "https://github.com/xenia-project/game-compatibility/issues"; + std::string url; + // Avoid searching for a title ID of "00000000". + uint32_t title_id = emulator_->title_id(); + if (!title_id) { + url = base_url; + } else { + url = fmt::format("{}?q=is%3Aissue+is%3Aopen+{:08X}", base_url, title_id); + } + LaunchWebBrowser(url); +} -void EmulatorWindow::ShowCommitID() { +void EmulatorWindow::ShowFAQ() { + LaunchWebBrowser("https://github.com/xenia-project/xenia/wiki/FAQ"); +} + +void EmulatorWindow::ShowBuildCommit() { #ifdef XE_BUILD_IS_PR LaunchWebBrowser( "https://github.com/xenia-project/xenia/pull/" XE_BUILD_PR_NUMBER); @@ -473,7 +1004,7 @@ void EmulatorWindow::UpdateTitle() { sb.Append(u8" (Preloading shaders\u2026)"); } - window_->set_title(sb.to_string_view()); + window_->SetTitle(sb.to_string_view()); } void EmulatorWindow::SetInitializingShaderStorage(bool initializing) { diff --git a/src/xenia/app/emulator_window.h b/src/xenia/app/emulator_window.h index 6dfb69080..c57d5f43b 100644 --- a/src/xenia/app/emulator_window.h +++ b/src/xenia/app/emulator_window.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,42 +13,124 @@ #include #include +#include "xenia/emulator.h" +#include "xenia/gpu/command_processor.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" #include "xenia/ui/menu_item.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" -namespace xe { -class Emulator; -} // namespace xe - namespace xe { namespace app { class EmulatorWindow { public: + enum : size_t { + // The UI is on top of the game and is open in special cases, so + // lowest-priority. + kZOrderHidInput, + kZOrderImGui, + kZOrderProfiler, + // Emulator window controls are expected to be always accessible by the + // user, so highest-priority. + kZOrderEmulatorWindowInput, + }; + + virtual ~EmulatorWindow(); + static std::unique_ptr Create( Emulator* emulator, ui::WindowedAppContext& app_context); Emulator* emulator() const { return emulator_; } ui::WindowedAppContext& app_context() const { return app_context_; } ui::Window* window() const { return window_.get(); } + ui::ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); } + + ui::Presenter* GetGraphicsSystemPresenter() const; + void SetupGraphicsSystemPresenterPainting(); + void ShutdownGraphicsSystemPresenterPainting(); + + void OnEmulatorInitialized(); void UpdateTitle(); + void SetFullscreen(bool fullscreen); void ToggleFullscreen(); void SetInitializingShaderStorage(bool initializing); private: + class EmulatorWindowListener final : public ui::WindowListener, + public ui::WindowInputListener { + public: + explicit EmulatorWindowListener(EmulatorWindow& emulator_window) + : emulator_window_(emulator_window) {} + + void OnClosing(ui::UIEvent& e) override; + void OnFileDrop(ui::FileDropEvent& e) override; + + void OnKeyDown(ui::KeyEvent& e) override; + + private: + EmulatorWindow& emulator_window_; + }; + + class DisplayConfigGameConfigLoadCallback + : public Emulator::GameConfigLoadCallback { + public: + DisplayConfigGameConfigLoadCallback(Emulator& emulator, + EmulatorWindow& emulator_window) + : Emulator::GameConfigLoadCallback(emulator), + emulator_window_(emulator_window) {} + + void PostGameConfigLoad() override; + + private: + EmulatorWindow& emulator_window_; + }; + + class DisplayConfigDialog final : public ui::ImGuiDialog { + public: + DisplayConfigDialog(ui::ImGuiDrawer* imgui_drawer, + EmulatorWindow& emulator_window) + : ui::ImGuiDialog(imgui_drawer), emulator_window_(emulator_window) {} + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + EmulatorWindow& emulator_window_; + }; + explicit EmulatorWindow(Emulator* emulator, ui::WindowedAppContext& app_context); bool Initialize(); + // For comparisons, use GetSwapPostEffectForCvarValue instead as the default + // fallback may be used for multiple values. + static const char* GetCvarValueForSwapPostEffect( + gpu::CommandProcessor::SwapPostEffect effect); + static gpu::CommandProcessor::SwapPostEffect GetSwapPostEffectForCvarValue( + const std::string& cvar_value); + // For comparisons, use GetGuestOutputPaintEffectForCvarValue instead as the + // default fallback may be used for multiple values. + static const char* GetCvarValueForGuestOutputPaintEffect( + ui::Presenter::GuestOutputPaintConfig::Effect effect); + static ui::Presenter::GuestOutputPaintConfig::Effect + GetGuestOutputPaintEffectForCvarValue(const std::string& cvar_value); + static ui::Presenter::GuestOutputPaintConfig + GetGuestOutputPaintConfigForCvars(); + void ApplyDisplayConfigForCvars(); + + void OnKeyDown(ui::KeyEvent& e); void FileDrop(const std::filesystem::path& filename); void FileOpen(); void FileClose(); void ShowContentDirectory(); - void CheckHideCursor(); void CpuTimeScalarReset(); void CpuTimeScalarSetHalf(); void CpuTimeScalarSetDouble(); @@ -56,15 +138,27 @@ class EmulatorWindow { void CpuBreakIntoHostDebugger(); void GpuTraceFrame(); void GpuClearCaches(); - void ShowHelpWebsite(); - void ShowCommitID(); + void ToggleDisplayConfigDialog(); + void ShowCompatibility(); + void ShowFAQ(); + void ShowBuildCommit(); Emulator* emulator_; ui::WindowedAppContext& app_context_; + EmulatorWindowListener window_listener_; std::unique_ptr window_; + std::unique_ptr imgui_drawer_; + std::unique_ptr + display_config_game_config_load_callback_; + // Creation may fail, in this case immediate drawer UI must not be drawn. + std::unique_ptr immediate_drawer_; + + bool emulator_initialized_ = false; + std::string base_title_; - uint64_t cursor_hide_time_ = 0; bool initializing_shader_storage_ = false; + + std::unique_ptr display_config_dialog_; }; } // namespace app diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index fd02de80a..c491e6510 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -28,6 +28,7 @@ #include "xenia/emulator.h" #include "xenia/ui/file_picker.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/vfs/devices/host_path_device.h" @@ -62,8 +63,6 @@ DEFINE_string(gpu, "any", "Graphics system. Use: [any, d3d12, vulkan, null]", DEFINE_string(hid, "any", "Input system. Use: [any, nop, sdl, winkey, xinput]", "HID"); -DEFINE_bool(fullscreen, false, "Toggles fullscreen", "GPU"); - DEFINE_path( storage_root, "", "Root path for persistent internal data storage (config, etc.), or empty " @@ -192,6 +191,17 @@ class EmulatorApp final : public xe::ui::WindowedApp { } }; + class DebugWindowClosedListener final : public xe::ui::WindowListener { + public: + explicit DebugWindowClosedListener(EmulatorApp& emulator_app) + : emulator_app_(emulator_app) {} + + void OnClosing(xe::ui::UIEvent& e) override; + + private: + EmulatorApp& emulator_app_; + }; + explicit EmulatorApp(xe::ui::WindowedAppContext& app_context); static std::unique_ptr CreateAudioSystem( @@ -203,6 +213,8 @@ class EmulatorApp final : public xe::ui::WindowedApp { void EmulatorThread(); void ShutdownEmulatorThreadFromUIThread(); + DebugWindowClosedListener debug_window_closed_listener_; + std::unique_ptr emulator_; std::unique_ptr emulator_window_; @@ -215,8 +227,15 @@ class EmulatorApp final : public xe::ui::WindowedApp { std::thread emulator_thread_; }; +void EmulatorApp::DebugWindowClosedListener::OnClosing(xe::ui::UIEvent& e) { + EmulatorApp* emulator_app = &emulator_app_; + emulator_app->emulator_->processor()->set_debug_listener(nullptr); + emulator_app->debug_window_.reset(); +} + EmulatorApp::EmulatorApp(xe::ui::WindowedAppContext& app_context) - : xe::ui::WindowedApp(app_context, "xenia", "[Path to .iso/.xex]") { + : xe::ui::WindowedApp(app_context, "xenia", "[Path to .iso/.xex]"), + debug_window_closed_listener_(*this) { AddPositionalOption("target"); } @@ -253,9 +272,10 @@ std::vector> EmulatorApp::CreateInputDrivers( ui::Window* window) { std::vector> drivers; if (cvars::hid.compare("nop") == 0) { - drivers.emplace_back(xe::hid::nop::Create(window)); + drivers.emplace_back( + xe::hid::nop::Create(window, EmulatorWindow::kZOrderHidInput)); } else { - Factory factory; + Factory factory; #if XE_PLATFORM_WIN32 factory.Add("xinput", xe::hid::xinput::Create); #endif // XE_PLATFORM_WIN32 @@ -264,14 +284,16 @@ std::vector> EmulatorApp::CreateInputDrivers( // WinKey input driver should always be the last input driver added! factory.Add("winkey", xe::hid::winkey::Create); #endif // XE_PLATFORM_WIN32 - for (auto& driver : factory.CreateAll(cvars::hid, window)) { + for (auto& driver : factory.CreateAll(cvars::hid, window, + EmulatorWindow::kZOrderHidInput)) { if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } } if (drivers.empty()) { // Fallback to nop if none created. - drivers.emplace_back(xe::hid::nop::Create(window)); + drivers.emplace_back( + xe::hid::nop::Create(window, EmulatorWindow::kZOrderHidInput)); } } return drivers; @@ -366,6 +388,9 @@ void EmulatorApp::OnDestroy() { // The profiler needs to shut down before the graphics context. Profiler::Shutdown(); + // Write all cvar overrides to the config. + config::SaveConfig(); + // TODO(DrChat): Remove this code and do a proper exit. XELOGI("Cheap-skate exit!"); std::quick_exit(EXIT_SUCCESS); @@ -379,15 +404,18 @@ void EmulatorApp::EmulatorThread() { // Setup and initialize all subsystems. If we can't do something // (unsupported system, memory issues, etc) this will fail early. - X_STATUS result = - emulator_->Setup(emulator_window_->window(), CreateAudioSystem, - CreateGraphicsSystem, CreateInputDrivers); + X_STATUS result = emulator_->Setup( + emulator_window_->window(), emulator_window_->imgui_drawer(), + CreateAudioSystem, CreateGraphicsSystem, CreateInputDrivers); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result); app_context().RequestDeferredQuit(); return; } + app_context().CallInUIThread( + [this]() { emulator_window_->SetupGraphicsSystemPresenterPainting(); }); + if (cvars::mount_scratch) { auto scratch_device = std::make_unique( "\\SCRATCH", "scratch", false); @@ -456,12 +484,8 @@ void EmulatorApp::EmulatorThread() { app_context().CallInUIThreadSynchronous([this]() { debug_window_ = xe::debug::ui::DebugWindow::Create(emulator_.get(), app_context()); - debug_window_->window()->on_closed.AddListener( - [this](xe::ui::UIEvent* e) { - emulator_->processor()->set_debug_listener(nullptr); - app_context().CallInUIThread( - [this]() { debug_window_.reset(); }); - }); + debug_window_->window()->AddListener( + &debug_window_closed_listener_); }); // If failed to enqueue the UI thread call, this will just be null. return debug_window_.get(); @@ -490,9 +514,9 @@ void EmulatorApp::EmulatorThread() { } }); - // Enable the main menu now that the emulator is properly loaded + // Enable emulator input now that the emulator is properly loaded. app_context().CallInUIThread( - [this]() { emulator_window_->window()->EnableMainMenu(); }); + [this]() { emulator_window_->OnEmulatorInitialized(); }); // Grab path from the flag or unnamed argument. std::filesystem::path path; @@ -500,12 +524,6 @@ void EmulatorApp::EmulatorThread() { path = cvars::target; } - // Toggles fullscreen - if (cvars::fullscreen) { - app_context().CallInUIThread( - [this]() { emulator_window_->ToggleFullscreen(); }); - } - if (!path.empty()) { // Normalize the path and make absolute. auto abs_path = std::filesystem::absolute(path); diff --git a/src/xenia/apu/xma_context.cc b/src/xenia/apu/xma_context.cc index a9662a0d8..e9047654a 100644 --- a/src/xenia/apu/xma_context.cc +++ b/src/xenia/apu/xma_context.cc @@ -177,6 +177,25 @@ void XmaContext::SwapInputBuffer(XMA_CONTEXT_DATA* data) { data->input_buffer_read_offset = 0; } +bool XmaContext::TrySetupNextLoop(XMA_CONTEXT_DATA* data, + bool ignore_input_buffer_offset) { + // Setup the input buffer offset if next loop exists. + // TODO(Pseudo-Kernel): Need to handle loop in the following cases. + // 1. loop_start == loop_end == 0 + // 2. loop_start > loop_end && loop_count > 0 + if (data->loop_count > 0 && data->loop_start < data->loop_end && + (ignore_input_buffer_offset || + data->input_buffer_read_offset >= data->loop_end)) { + // Loop back to the beginning. + data->input_buffer_read_offset = data->loop_start; + if (data->loop_count < 255) { + data->loop_count--; + } + return true; + } + return false; +} + /* void XmaContext::NextPacket( uint8_t* input_buffer, @@ -364,6 +383,7 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { assert_false(data->stop_when_done); assert_false(data->interrupt_when_done); static int total_samples = 0; + bool reuse_input_buffer = false; // Decode until we can't write any more data. while (output_remaining_bytes > 0) { if (!data->input_buffer_0_valid && !data->input_buffer_1_valid) { @@ -371,6 +391,10 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { break; } + // Setup the input buffer if we are at loop_end. + // The input buffer must not be swapped out until all loops are processed. + reuse_input_buffer = TrySetupNextLoop(data, false); + // assert_true(packets_skip_ == 0); // assert_true(split_frame_len_ == 0); // assert_true(split_frame_len_partial_ == 0); @@ -392,7 +416,13 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { packets_skip_--; packet_idx++; if (packet_idx >= current_input_packet_count) { - SwapInputBuffer(data); + if (!reuse_input_buffer) { + // Last packet. Try setup once more. + reuse_input_buffer = TrySetupNextLoop(data, true); + } + if (!reuse_input_buffer) { + SwapInputBuffer(data); + } return; } } @@ -524,7 +554,13 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { packet += kBytesPerPacket; packet_idx++; if (packet_idx >= current_input_packet_count) { - SwapInputBuffer(data); + if (!reuse_input_buffer) { + // Last packet. Try setup once more. + reuse_input_buffer = TrySetupNextLoop(data, true); + } + if (!reuse_input_buffer) { + SwapInputBuffer(data); + } return; } } @@ -606,7 +642,13 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { packets_skip_--; packet_idx++; if (packet_idx >= current_input_packet_count) { - SwapInputBuffer(data); + if (!reuse_input_buffer) { + // Last packet. Try setup once more. + reuse_input_buffer = TrySetupNextLoop(data, true); + } + if (!reuse_input_buffer) { + SwapInputBuffer(data); + } return; } } @@ -618,7 +660,13 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { // Next packet but we already skipped to it if (packet_idx >= current_input_packet_count) { // Buffer is fully used - SwapInputBuffer(data); + if (!reuse_input_buffer) { + // Last packet. Try setup once more. + reuse_input_buffer = TrySetupNextLoop(data, true); + } + if (!reuse_input_buffer) { + SwapInputBuffer(data); + } break; } offset = diff --git a/src/xenia/apu/xma_context.h b/src/xenia/apu/xma_context.h index d9e9b360a..52e97ee47 100644 --- a/src/xenia/apu/xma_context.h +++ b/src/xenia/apu/xma_context.h @@ -171,6 +171,8 @@ class XmaContext { private: static void SwapInputBuffer(XMA_CONTEXT_DATA* data); + static bool TrySetupNextLoop(XMA_CONTEXT_DATA* data, + bool ignore_input_buffer_offset); static void NextPacket(XMA_CONTEXT_DATA* data); static int GetSampleRate(int id); // Get the offset of the next frame. Does not traverse packets. diff --git a/src/xenia/base/arena.cc b/src/xenia/base/arena.cc index 66184f0f2..809b72af7 100644 --- a/src/xenia/base/arena.cc +++ b/src/xenia/base/arena.cc @@ -60,7 +60,7 @@ void* Arena::Alloc(size_t size, size_t align) { if (active_chunk_) { if (active_chunk_->capacity - active_chunk_->offset < - size + get_padding() + 4096) { + size + get_padding() + 4_KiB) { Chunk* next = active_chunk_->next; if (!next) { assert_true(size + get_padding() < chunk_size_, diff --git a/src/xenia/base/arena.h b/src/xenia/base/arena.h index 7dbdb7c2a..204fa555c 100644 --- a/src/xenia/base/arena.h +++ b/src/xenia/base/arena.h @@ -14,11 +14,15 @@ #include #include +#include "xenia/base/literals.h" + namespace xe { +using namespace xe::literals; + class Arena { public: - explicit Arena(size_t chunk_size = 4 * 1024 * 1024); + explicit Arena(size_t chunk_size = 4_MiB); ~Arena(); void Reset(); diff --git a/src/xenia/base/console_app_main_android.cc b/src/xenia/base/console_app_main_android.cc index 320128bc1..3e2f79473 100644 --- a/src/xenia/base/console_app_main_android.cc +++ b/src/xenia/base/console_app_main_android.cc @@ -24,7 +24,7 @@ extern "C" int main(int argc, char** argv) { // Initialize Android globals, including logging. Needs parsed cvars. // TODO(Triang3l): Obtain the actual API level. - xe::InitializeAndroidAppFromMainThread(__ANDROID_API__); + xe::InitializeAndroidAppFromMainThread(__ANDROID_API__, nullptr, nullptr); std::vector args; for (int n = 0; n < argc; n++) { diff --git a/src/xenia/base/console_app_main_win.cc b/src/xenia/base/console_app_main_win.cc index cd2a38dc4..6cc700eec 100644 --- a/src/xenia/base/console_app_main_win.cc +++ b/src/xenia/base/console_app_main_win.cc @@ -13,7 +13,8 @@ #include "xenia/base/console_app_main.h" #include "xenia/base/main_win.h" -int main(int argc_ignored, char** argv_ignored) { +// A wide character entry point is required for functions like _get_wpgmptr. +int wmain(int argc_ignored, wchar_t** argv_ignored) { xe::ConsoleAppEntryInfo entry_info = xe::GetConsoleAppEntryInfo(); std::vector args; diff --git a/src/xenia/base/console_win.cc b/src/xenia/base/console_win.cc index e6b8fb887..252e99b84 100644 --- a/src/xenia/base/console_win.cc +++ b/src/xenia/base/console_win.cc @@ -27,7 +27,7 @@ static bool has_shell_environment_variable() { size_t size = 0; // Check if SHELL exists // If it doesn't, then we are in a Windows Terminal - auto error = getenv_s(&size, nullptr, 0, "SHELL"); + auto error = _wgetenv_s(&size, nullptr, 0, L"SHELL"); if (error) { return false; } diff --git a/src/xenia/base/cvar.h b/src/xenia/base/cvar.h index 1f92d0766..585039fd6 100644 --- a/src/xenia/base/cvar.h +++ b/src/xenia/base/cvar.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -86,6 +86,10 @@ class ConfigVar : public CommandVar, virtual public IConfigVar { void LoadGameConfigValue(std::shared_ptr result) override; void SetConfigValue(T val); void SetGameConfigValue(T val); + // Changes the actual value used to the one specified, and also makes it the + // one that will be stored when the global config is written next time. After + // overriding, however, the next game config loaded may still change it. + void OverrideConfigValue(T val); private: std::string category_; @@ -260,6 +264,16 @@ void ConfigVar::SetGameConfigValue(T val) { UpdateValue(); } template +void ConfigVar::OverrideConfigValue(T val) { + config_value_ = std::make_unique(val); + // The user explicitly changes the value at runtime and wants it to take + // effect immediately. Drop everything with a higher priority. The next game + // config load, however, may still change it. + game_config_value_.reset(); + this->commandline_value_.reset(); + UpdateValue(); +} +template void ConfigVar::ResetConfigValueToDefault() { SetConfigValue(this->default_value_); } @@ -373,6 +387,28 @@ ICommandVar* define_cmdvar(const char* name, T* default_value, extern type name; \ } +#define ACCESS_CVar(name) (*cv::cv_##name) + +// dynamic_cast is needed because of virtual inheritance. +#define OVERRIDE_CVar(name, type, value) \ + dynamic_cast*>(&ACCESS_CVar(name)) \ + ->OverrideConfigValue(value); + +#define OVERRIDE_bool(name, value) OVERRIDE_CVar(name, bool, value) + +#define OVERRIDE_int32(name, value) OVERRIDE_CVar(name, int32_t, value) + +#define OVERRIDE_uint32(name, value) OVERRIDE_CVar(name, uint32_t, value) + +#define OVERRIDE_uint64(name, value) OVERRIDE_CVar(name, uint64_t, value) + +#define OVERRIDE_double(name, value) OVERRIDE_CVar(name, double, value) + +#define OVERRIDE_string(name, value) OVERRIDE_CVar(name, std::string, value) + +#define OVERRIDE_path(name, value) \ + OVERRIDE_CVar(name, std::filesystem::path, value) + // Interface for changing the default value of a variable with auto-upgrading of // users' configs (to distinguish between a leftover old default and an explicit // override), without having to rename the variable. diff --git a/src/xenia/base/filesystem.h b/src/xenia/base/filesystem.h index 036a6a7a4..c8cff150f 100644 --- a/src/xenia/base/filesystem.h +++ b/src/xenia/base/filesystem.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -41,8 +41,8 @@ std::filesystem::path GetUserFolder(); // attempting to create it. bool CreateParentFolder(const std::filesystem::path& path); -// Creates an empty file at the given path. -bool CreateFile(const std::filesystem::path& path); +// Creates an empty file at the given path, overwriting if it exists. +bool CreateEmptyFile(const std::filesystem::path& path); // Opens the file at the given path with the specified mode. // This behaves like fopen and the returned handle can be used with stdio. diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index 497c98bd3..2e9ddb2c5 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -122,7 +122,7 @@ static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) { return filetime; } -bool CreateFile(const std::filesystem::path& path) { +bool CreateEmptyFile(const std::filesystem::path& path) { int file = creat(path.c_str(), 0774); if (file >= 0) { close(file); diff --git a/src/xenia/base/filesystem_win.cc b/src/xenia/base/filesystem_win.cc index 9daf15af5..f1f16c063 100644 --- a/src/xenia/base/filesystem_win.cc +++ b/src/xenia/base/filesystem_win.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -60,7 +60,7 @@ std::filesystem::path GetUserFolder() { return result; } -bool CreateFile(const std::filesystem::path& path) { +bool CreateEmptyFile(const std::filesystem::path& path) { auto handle = CreateFileW(path.c_str(), 0, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (handle == INVALID_HANDLE_VALUE) { diff --git a/src/xenia/base/literals.h b/src/xenia/base/literals.h new file mode 100644 index 000000000..d4b0a66b6 --- /dev/null +++ b/src/xenia/base/literals.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_BASE_LITERALS_H_ +#define XENIA_BASE_LITERALS_H_ + +#include + +namespace xe::literals { + +constexpr size_t operator""_KiB(unsigned long long int x) { + return 1024ULL * x; +} + +constexpr size_t operator""_MiB(unsigned long long int x) { + return 1024_KiB * x; +} + +constexpr size_t operator""_GiB(unsigned long long int x) { + return 1024_MiB * x; +} + +constexpr size_t operator""_TiB(unsigned long long int x) { + return 1024_GiB * x; +} + +constexpr size_t operator""_PiB(unsigned long long int x) { + return 1024_TiB * x; +} + +} // namespace xe::literals + +#endif // XENIA_BASE_LITERALS_H_ diff --git a/src/xenia/base/logging.cc b/src/xenia/base/logging.cc index ef04ec192..bed2fe43b 100644 --- a/src/xenia/base/logging.cc +++ b/src/xenia/base/logging.cc @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/filesystem.h" +#include "xenia/base/literals.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" #include "xenia/base/platform.h" @@ -59,6 +61,7 @@ DEFINE_int32( "Logging"); namespace dp = disruptorplus; +using namespace xe::literals; namespace xe { @@ -74,7 +77,7 @@ struct LogLine { char prefix_char; }; -thread_local char thread_log_buffer_[64 * 1024]; +thread_local char thread_log_buffer_[64_KiB]; FileLogSink::~FileLogSink() { if (file_) { @@ -234,7 +237,7 @@ class Logger { } private: - static const size_t kBufferSize = 8 * 1024 * 1024; + static const size_t kBufferSize = 8_MiB; uint8_t buffer_[kBufferSize]; static const size_t kBlockSize = 256; @@ -498,7 +501,13 @@ void FatalError(const std::string_view str) { } ShutdownLogging(); - std::exit(1); + +#if XE_PLATFORM_ANDROID + // Throw an error that can be reported to the developers via the store. + std::abort(); +#else + std::exit(EXIT_FAILURE); +#endif // XE_PLATFORM_ANDROID } } // namespace xe diff --git a/src/xenia/base/main_android.cc b/src/xenia/base/main_android.cc index 56211fee2..a44ca7d3b 100644 --- a/src/xenia/base/main_android.cc +++ b/src/xenia/base/main_android.cc @@ -9,11 +9,15 @@ #include "xenia/base/main_android.h" +#include +#include #include +#include #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/memory.h" +#include "xenia/base/system.h" #include "xenia/base/threading.h" namespace xe { @@ -22,7 +26,25 @@ static size_t android_initializations_ = 0; static int32_t android_api_level_ = __ANDROID_API__; -void InitializeAndroidAppFromMainThread(int32_t api_level) { +static JNIEnv* android_main_thread_jni_env_ = nullptr; +static JavaVM* android_java_vm_ = nullptr; +static pthread_key_t android_thread_jni_env_key_; +static jobject android_application_context_ = nullptr; + +static void AndroidThreadJNIEnvDestructor(void* jni_env_pointer) { + // The JNIEnv pointer for the main thread is taken externally, the lifetime of + // the attachment is not managed by the key. + JNIEnv* jni_env = static_cast(jni_env_pointer); + if (jni_env && jni_env != android_main_thread_jni_env_) { + android_java_vm_->DetachCurrentThread(); + } + // Multiple iterations of destructor invocations can be done - clear. + pthread_setspecific(android_thread_jni_env_key_, nullptr); +} + +void InitializeAndroidAppFromMainThread(int32_t api_level, + JNIEnv* main_thread_jni_env, + jobject application_context) { if (android_initializations_++) { // Already initialized for another component in the process. return; @@ -32,6 +54,45 @@ void InitializeAndroidAppFromMainThread(int32_t api_level) { // subsystem initialization itself. android_api_level_ = api_level; + android_main_thread_jni_env_ = main_thread_jni_env; + if (main_thread_jni_env) { + // In a Java VM, not just in a process that runs an executable - set up + // the attachment of threads to the Java VM. + if (main_thread_jni_env->GetJavaVM(&android_java_vm_) < 0) { + // Logging has not been initialized yet. + __android_log_write( + ANDROID_LOG_ERROR, "InitializeAndroidAppFromMainThread", + "Failed to get the Java VM from the JNI environment of the main " + "thread"); + std::abort(); + } + if (pthread_key_create(&android_thread_jni_env_key_, + AndroidThreadJNIEnvDestructor)) { + __android_log_write( + ANDROID_LOG_ERROR, "InitializeAndroidAppFromMainThread", + "Failed to create the thread-specific JNI environment key"); + std::abort(); + } + if (pthread_setspecific(android_thread_jni_env_key_, main_thread_jni_env)) { + __android_log_write( + ANDROID_LOG_ERROR, "InitializeAndroidAppFromMainThread", + "Failed to set the thread-specific JNI environment pointer for the " + "main thread"); + std::abort(); + } + if (application_context) { + android_application_context_ = + main_thread_jni_env->NewGlobalRef(application_context); + if (!android_application_context_) { + __android_log_write( + ANDROID_LOG_ERROR, "InitializeAndroidAppFromMainThread", + "Failed to create a global reference to the application context " + "object"); + std::abort(); + } + } + } + // Logging uses threading. xe::threading::AndroidInitialize(); @@ -40,6 +101,15 @@ void InitializeAndroidAppFromMainThread(int32_t api_level) { xe::InitializeLogging("xenia"); xe::memory::AndroidInitialize(); + + if (android_application_context_) { + if (!xe::InitializeAndroidSystemForApplicationContext()) { + __android_log_write(ANDROID_LOG_ERROR, + "InitializeAndroidAppFromMainThread", + "Failed to initialize system UI interaction"); + std::abort(); + } + } } void ShutdownAndroidAppFromMainThread() { @@ -52,15 +122,36 @@ void ShutdownAndroidAppFromMainThread() { return; } + xe::ShutdownAndroidSystem(); + xe::memory::AndroidShutdown(); xe::ShutdownLogging(); xe::threading::AndroidShutdown(); + if (android_application_context_) { + android_main_thread_jni_env_->DeleteGlobalRef(android_application_context_); + android_application_context_ = nullptr; + } + if (android_java_vm_) { + android_java_vm_ = nullptr; + pthread_key_delete(android_thread_jni_env_key_); + } + android_main_thread_jni_env_ = nullptr; + android_api_level_ = __ANDROID_API__; } int32_t GetAndroidApiLevel() { return android_api_level_; } +JNIEnv* GetAndroidThreadJniEnv() { + if (!android_java_vm_) { + return nullptr; + } + return static_cast(pthread_getspecific(android_thread_jni_env_key_)); +} + +jobject GetAndroidApplicationContext() { return android_application_context_; } + } // namespace xe diff --git a/src/xenia/base/main_android.h b/src/xenia/base/main_android.h index 1f2d23dd2..e74a82ffe 100644 --- a/src/xenia/base/main_android.h +++ b/src/xenia/base/main_android.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_BASE_MAIN_ANDROID_H_ #define XENIA_BASE_MAIN_ANDROID_H_ +#include #include #include "xenia/base/platform.h" @@ -27,14 +28,33 @@ namespace xe { // counting internally. // // In standalone console apps built with $(BUILD_EXECUTABLE), these functions -// must be called in `main`. -void InitializeAndroidAppFromMainThread(int32_t api_level); +// must be called in `main`, with a null main thread JNI environment. +void InitializeAndroidAppFromMainThread(int32_t api_level, + JNIEnv* main_thread_jni_env, + jobject application_context); void ShutdownAndroidAppFromMainThread(); // May be the minimum supported level if the initialization was done without a // configuration. int32_t GetAndroidApiLevel(); +// Useful notes about JNI usage on Android within Xenia: +// - All static libraries defining JNI native functions must be linked to shared +// libraries via LOCAL_WHOLE_STATIC_LIBRARIES. +// - If method or field IDs are cached, a global reference to the class needs to +// be held - it prevents the class from being unloaded by the class loaders +// (in a way that would make the IDs invalid when it's reloaded). +// - GetStringUTFChars (UTF-8) returns null-terminated strings, GetStringChars +// (UTF-16) does not. + +// May return null if not in a Java VM process, or in case of a failure to +// attach on a non-main thread. +JNIEnv* GetAndroidThreadJniEnv(); +// Returns the global reference if in an application context, or null otherwise. +// This is the application context, not the activity one, because multiple +// activities may be running in one process. +jobject GetAndroidApplicationContext(); + } // namespace xe #endif // XENIA_BASE_MAIN_ANDROID_H_ diff --git a/src/xenia/base/main_win.cc b/src/xenia/base/main_win.cc index 33bd65e75..b6eaa4a7b 100644 --- a/src/xenia/base/main_win.cc +++ b/src/xenia/base/main_win.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -19,37 +19,64 @@ // Autogenerated by `xb premake`. #include "build/version.h" -// For RequestHighPerformance. +// For RequestWin32MMCSS. +#include +// For RequestWin32HighResolutionTimer. #include -DEFINE_bool(win32_high_freq, true, - "Requests high performance from the NT kernel", "Kernel"); +DEFINE_bool(win32_high_resolution_timer, true, + "Requests high-resolution timer from the NT kernel", "Win32"); +DEFINE_bool( + win32_mmcss, true, + "Opt in the Multimedia Class Scheduler Service (MMCSS) scheduling for " + "prioritized access to CPU resources", + "Win32"); namespace xe { -static void RequestHighPerformance() { -#if XE_PLATFORM_WIN32 - NTSTATUS(*NtQueryTimerResolution) - (OUT PULONG MinimumResolution, OUT PULONG MaximumResolution, - OUT PULONG CurrentResolution); +static void RequestWin32HighResolutionTimer() { + HMODULE ntdll_module = GetModuleHandleW(L"ntdll.dll"); + if (!ntdll_module) { + return; + } - NTSTATUS(*NtSetTimerResolution) - (IN ULONG DesiredResolution, IN BOOLEAN SetResolution, - OUT PULONG CurrentResolution); - - NtQueryTimerResolution = (decltype(NtQueryTimerResolution))GetProcAddress( - GetModuleHandleW(L"ntdll.dll"), "NtQueryTimerResolution"); - NtSetTimerResolution = (decltype(NtSetTimerResolution))GetProcAddress( - GetModuleHandleW(L"ntdll.dll"), "NtSetTimerResolution"); - if (!NtQueryTimerResolution || !NtSetTimerResolution) { + // clang-format off + NTSTATUS (NTAPI* nt_query_timer_resolution)(OUT PULONG MinimumResolution, + OUT PULONG MaximumResolution, + OUT PULONG CurrentResolution); + NTSTATUS (NTAPI* nt_set_timer_resolution)(IN ULONG DesiredResolution, + IN BOOLEAN SetResolution, + OUT PULONG CurrentResolution); + // clang-format on + nt_query_timer_resolution = + reinterpret_cast( + GetProcAddress(ntdll_module, "NtQueryTimerResolution")); + nt_set_timer_resolution = reinterpret_cast( + GetProcAddress(ntdll_module, "NtSetTimerResolution")); + if (!nt_query_timer_resolution || !nt_set_timer_resolution) { return; } ULONG minimum_resolution, maximum_resolution, current_resolution; - NtQueryTimerResolution(&minimum_resolution, &maximum_resolution, - ¤t_resolution); - NtSetTimerResolution(maximum_resolution, TRUE, ¤t_resolution); -#endif + nt_query_timer_resolution(&minimum_resolution, &maximum_resolution, + ¤t_resolution); + nt_set_timer_resolution(maximum_resolution, TRUE, ¤t_resolution); +} + +static void RequestWin32MMCSS() { + HMODULE dwmapi_module = LoadLibraryW(L"dwmapi.dll"); + if (!dwmapi_module) { + return; + } + // clang-format off + HRESULT (STDAPICALLTYPE* dwm_enable_mmcss)(BOOL fEnableMMCSS); + // clang-format on + dwm_enable_mmcss = reinterpret_cast( + GetProcAddress(dwmapi_module, "DwmEnableMMCSS")); + if (dwm_enable_mmcss) { + dwm_enable_mmcss(TRUE); + } + FreeLibrary(dwmapi_module); } bool ParseWin32LaunchArguments( @@ -103,9 +130,12 @@ int InitializeWin32App(const std::string_view app_name) { #endif XE_BUILD_BRANCH "@" XE_BUILD_COMMIT_SHORT " on " XE_BUILD_DATE); - // Request high performance timing. - if (cvars::win32_high_freq) { - RequestHighPerformance(); + // Request high-performance timing and scheduling. + if (cvars::win32_high_resolution_timer) { + RequestWin32HighResolutionTimer(); + } + if (cvars::win32_mmcss) { + RequestWin32MMCSS(); } return 0; diff --git a/src/xenia/base/memory.cc b/src/xenia/base/memory.cc index 8acbf43bd..5c1763282 100644 --- a/src/xenia/base/memory.cc +++ b/src/xenia/base/memory.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -11,6 +11,10 @@ #include "xenia/base/cvar.h" #include "xenia/base/platform.h" +#if XE_ARCH_ARM64 +#include +#endif + #include DEFINE_bool( @@ -184,8 +188,8 @@ void copy_and_swap_64_unaligned(void* dest_ptr, const void* src_ptr, void copy_and_swap_16_in_32_aligned(void* dest_ptr, const void* src_ptr, size_t count) { - auto dest = reinterpret_cast(dest_ptr); - auto src = reinterpret_cast(src_ptr); + auto dest = reinterpret_cast(dest_ptr); + auto src = reinterpret_cast(src_ptr); size_t i; for (i = 0; i + 4 <= count; i += 4) { __m128i input = _mm_load_si128(reinterpret_cast(&src[i])); @@ -201,8 +205,8 @@ void copy_and_swap_16_in_32_aligned(void* dest_ptr, const void* src_ptr, void copy_and_swap_16_in_32_unaligned(void* dest_ptr, const void* src_ptr, size_t count) { - auto dest = reinterpret_cast(dest_ptr); - auto src = reinterpret_cast(src_ptr); + auto dest = reinterpret_cast(dest_ptr); + auto src = reinterpret_cast(src_ptr); size_t i; for (i = 0; i + 4 <= count; i += 4) { __m128i input = _mm_loadu_si128(reinterpret_cast(&src[i])); @@ -215,7 +219,133 @@ void copy_and_swap_16_in_32_unaligned(void* dest_ptr, const void* src_ptr, dest[i] = (src[i] >> 16) | (src[i] << 16); } } + +#elif XE_ARCH_ARM64 + +// Although NEON offers vector rev instructions (like vrev32q_u8), they are +// slower in benchmarks. Also, using uint8x16xN_t wasn't any faster in the +// benchmarks, hence we use just use one SIMD register to minimize residual +// processing. + +void copy_and_swap_16_aligned(void* dst_ptr, const void* src_ptr, + size_t count) { + copy_and_swap_16_unaligned(dst_ptr, src_ptr, count); +} + +void copy_and_swap_16_unaligned(void* dst_ptr, const void* src_ptr, + size_t count) { + auto dst = reinterpret_cast(dst_ptr); + auto src = reinterpret_cast(src_ptr); + + const uint8x16_t tbl_idx = + vcombine_u8(vcreate_u8(UINT64_C(0x0607040502030001)), + vcreate_u8(UINT64_C(0x0E0F0C0D0A0B0809))); + + while (count >= 8) { + uint8x16_t data = vld1q_u8(src); + data = vqtbl1q_u8(data, tbl_idx); + vst1q_u8(dst, data); + + count -= 8; + // These pointer increments will be combined with the load/stores (ldr/str) + // into single instructions (at least by clang) + dst += 16; + src += 16; + } + + while (count > 0) { + store_and_swap(dst, load(src)); + + count--; + dst += 2; + src += 2; + } +} + +void copy_and_swap_32_aligned(void* dst, const void* src, size_t count) { + copy_and_swap_32_unaligned(dst, src, count); +} + +void copy_and_swap_32_unaligned(void* dst_ptr, const void* src_ptr, + size_t count) { + auto dst = reinterpret_cast(dst_ptr); + auto src = reinterpret_cast(src_ptr); + + const uint8x16_t tbl_idx = + vcombine_u8(vcreate_u8(UINT64_C(0x405060700010203)), + vcreate_u8(UINT64_C(0x0C0D0E0F08090A0B))); + + while (count >= 4) { + uint8x16_t data = vld1q_u8(src); + data = vqtbl1q_u8(data, tbl_idx); + vst1q_u8(dst, data); + + count -= 4; + dst += 16; + src += 16; + } + + while (count > 0) { + store_and_swap(dst, load(src)); + + count--; + dst += 4; + src += 4; + } +} + +void copy_and_swap_64_aligned(void* dst, const void* src, size_t count) { + copy_and_swap_64_unaligned(dst, src, count); +} + +void copy_and_swap_64_unaligned(void* dst_ptr, const void* src_ptr, + size_t count) { + auto dst = reinterpret_cast(dst_ptr); + auto src = reinterpret_cast(src_ptr); + + const uint8x16_t tbl_idx = + vcombine_u8(vcreate_u8(UINT64_C(0x0001020304050607)), + vcreate_u8(UINT64_C(0x08090A0B0C0D0E0F))); + + while (count >= 2) { + uint8x16_t data = vld1q_u8(src); + data = vqtbl1q_u8(data, tbl_idx); + vst1q_u8(dst, data); + + count -= 2; + dst += 16; + src += 16; + } + + while (count > 0) { + store_and_swap(dst, load(src)); + + count--; + dst += 8; + src += 8; + } +} + +void copy_and_swap_16_in_32_aligned(void* dst, const void* src, size_t count) { + return copy_and_swap_16_in_32_unaligned(dst, src, count); +} + +void copy_and_swap_16_in_32_unaligned(void* dst_ptr, const void* src_ptr, + size_t count) { + auto dst = reinterpret_cast(dst_ptr); + auto src = reinterpret_cast(src_ptr); + while (count > 0) { + uint16_t word0 = *src++; + uint16_t word1 = *src++; + *dst++ = word1; + *dst++ = word0; + + count--; + } +} + #else + // Generic routines. void copy_and_swap_16_aligned(void* dest, const void* src, size_t count) { return copy_and_swap_16_unaligned(dest, src, count); @@ -260,14 +390,20 @@ void copy_and_swap_16_in_32_aligned(void* dest, const void* src, size_t count) { return copy_and_swap_16_in_32_unaligned(dest, src, count); } -void copy_and_swap_16_in_32_unaligned(void* dest_ptr, const void* src_ptr, +void copy_and_swap_16_in_32_unaligned(void* dst_ptr, const void* src_ptr, size_t count) { - auto dest = reinterpret_cast(dest_ptr); - auto src = reinterpret_cast(src_ptr); - for (size_t i = 0; i < count; ++i) { - dest[i] = (src[i] >> 16) | (src[i] << 16); + auto dst = reinterpret_cast(dst_ptr); + auto src = reinterpret_cast(src_ptr); + while (count > 0) { + uint16_t word0 = *src++; + uint16_t word1 = *src++; + *dst++ = word1; + *dst++ = word0; + + count--; } } + #endif } // namespace xe diff --git a/src/xenia/base/profiling.cc b/src/xenia/base/profiling.cc index bf24d4f7d..800ab8680 100644 --- a/src/xenia/base/profiling.cc +++ b/src/xenia/base/profiling.cc @@ -2,17 +2,20 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ +#include #include // NOTE: this must be included before microprofile as macro expansion needs // XELOGI. #include "xenia/base/logging.h" +#include "third_party/fmt/include/fmt/printf.h" + // NOTE: microprofile must be setup first, before profiling.h is included. #define MICROPROFILE_ENABLED 1 #define MICROPROFILEUI_ENABLED 1 @@ -21,7 +24,11 @@ #define MICROPROFILE_PER_THREAD_BUFFER_SIZE (1024 * 1024 * 10) #define MICROPROFILE_USE_THREAD_NAME_CALLBACK 1 #define MICROPROFILE_WEBSERVER_MAXFRAMES 3 -#define MICROPROFILE_PRINTF XELOGI +#define MICROPROFILE_PRINTF(...) \ + do { \ + auto xenia_profiler_formatted = fmt::sprintf(__VA_ARGS__); \ + XELOGI("{}", xenia_profiler_formatted); \ + } while (false); #define MICROPROFILE_WEBSERVER 0 #define MICROPROFILE_DEBUG 0 #define MICROPROFILE_MAX_THREADS 128 @@ -30,6 +37,7 @@ #include "xenia/base/assert.h" #include "xenia/base/cvar.h" #include "xenia/base/profiling.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" @@ -38,21 +46,27 @@ #endif // XE_OPTION_PROFILING #if XE_OPTION_PROFILING_UI -#undef DrawText #include "xenia/ui/microprofile_drawer.h" #endif // XE_OPTION_PROFILING_UI +DEFINE_bool(profiler_dpi_scaling, false, + "Apply window DPI scaling to the profiler.", "UI"); DEFINE_bool(show_profiler, false, "Show profiling UI by default.", "UI"); namespace xe { -#if XE_OPTION_PROFILING_UI -ui::Window* Profiler::window_ = nullptr; -std::unique_ptr Profiler::drawer_ = nullptr; -#endif // XE_OPTION_PROFILING_UI - #if XE_OPTION_PROFILING +Profiler::ProfilerWindowInputListener Profiler::input_listener_; +size_t Profiler::z_order_ = 0; +ui::Window* Profiler::window_ = nullptr; +#if XE_OPTION_PROFILING_UI +Profiler::ProfilerUIDrawer Profiler::ui_drawer_; +ui::Presenter* Profiler::presenter_ = nullptr; +std::unique_ptr Profiler::drawer_; +bool Profiler::dpi_scaling_ = false; +#endif // XE_OPTION_PROFILING_UI + bool Profiler::is_enabled() { return true; } bool Profiler::is_visible() { return is_enabled() && MicroProfileIsDrawing(); } @@ -73,6 +87,7 @@ void Profiler::Initialize() { g_MicroProfile.nActiveBars |= 0x1 | 0x2; #if XE_OPTION_PROFILING_UI + dpi_scaling_ = cvars::profiler_dpi_scaling; MicroProfileInitUI(); g_MicroProfileUI.bShowSpikes = true; g_MicroProfileUI.nOpacityBackground = 0x40u << 24; @@ -96,7 +111,7 @@ void Profiler::Dump() { } void Profiler::Shutdown() { - drawer_.reset(); + SetUserIO(0, nullptr, nullptr, nullptr); window_ = nullptr; MicroProfileShutdown(); } @@ -113,144 +128,208 @@ void Profiler::ThreadEnter(const char* name) { void Profiler::ThreadExit() { MicroProfileOnThreadExit(); } -bool Profiler::OnKeyDown(ui::VirtualKey virtual_key) { +void Profiler::ProfilerWindowInputListener::OnKeyDown(ui::KeyEvent& e) { // https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx - switch (virtual_key) { + bool handled = true; + switch (e.virtual_key()) { case ui::VirtualKey::kOem3: // ` MicroProfileTogglePause(); - return true; + break; #if XE_OPTION_PROFILING_UI case ui::VirtualKey::kTab: - MicroProfileToggleDisplayMode(); - return true; + ToggleDisplay(); + break; case ui::VirtualKey::k1: MicroProfileModKey(1); - return true; + break; #endif // XE_OPTION_PROFILING_UI default: + handled = false; break; } - return false; + if (handled) { + e.set_handled(true); + } + PostInputEvent(); } -bool Profiler::OnKeyUp(ui::VirtualKey virtual_key) { - switch (virtual_key) { +void Profiler::ProfilerWindowInputListener::OnKeyUp(ui::KeyEvent& e) { + bool handled = true; + switch (e.virtual_key()) { #if XE_OPTION_PROFILING_UI case ui::VirtualKey::k1: MicroProfileModKey(0); - return true; + break; #endif // XE_OPTION_PROFILING_UI default: + handled = false; break; } - return false; + if (handled) { + e.set_handled(true); + } + PostInputEvent(); } #if XE_OPTION_PROFILING_UI -void Profiler::OnMouseDown(bool left_button, bool right_button) { - MicroProfileMouseButton(left_button, right_button); +void Profiler::ProfilerWindowInputListener::OnMouseDown(ui::MouseEvent& e) { + Profiler::SetMousePosition(e.x(), e.y(), 0); + MicroProfileMouseButton(e.button() == ui::MouseEvent::Button::kLeft, + e.button() == ui::MouseEvent::Button::kRight); + e.set_handled(true); + PostInputEvent(); } -void Profiler::OnMouseUp() { MicroProfileMouseButton(0, 0); } - -void Profiler::OnMouseMove(int x, int y) { MicroProfileMousePosition(x, y, 0); } - -void Profiler::OnMouseWheel(int x, int y, int dy) { - MicroProfileMousePosition(x, y, dy); +void Profiler::ProfilerWindowInputListener::OnMouseUp(ui::MouseEvent& e) { + Profiler::SetMousePosition(e.x(), e.y(), 0); + MicroProfileMouseButton(0, 0); + e.set_handled(true); + PostInputEvent(); } -void Profiler::ToggleDisplay() { MicroProfileToggleDisplayMode(); } +void Profiler::ProfilerWindowInputListener::OnMouseMove(ui::MouseEvent& e) { + Profiler::SetMousePosition(e.x(), e.y(), 0); + e.set_handled(true); + PostInputEvent(); +} + +void Profiler::ProfilerWindowInputListener::OnMouseWheel(ui::MouseEvent& e) { + Profiler::SetMousePosition(e.x(), e.y(), e.scroll_y()); + e.set_handled(true); + PostInputEvent(); +} void Profiler::TogglePause() { MicroProfileTogglePause(); } #else -void Profiler::OnMouseDown(bool left_button, bool right_button) {} - -void Profiler::OnMouseUp() {} - -void Profiler::OnMouseMove(int x, int y) {} - -void Profiler::OnMouseWheel(int x, int y, int dy) {} - -void Profiler::ToggleDisplay() {} - void Profiler::TogglePause() {} #endif // XE_OPTION_PROFILING_UI -void Profiler::set_window(ui::Window* window) { - assert_null(window_); +void Profiler::ToggleDisplay() { + bool was_visible = is_visible(); + MicroProfileToggleDisplayMode(); + if (is_visible() != was_visible) { + if (window_) { + if (was_visible) { + window_->RemoveInputListener(&input_listener_); + } else { + window_->AddInputListener(&input_listener_, z_order_); + } + } +#if XE_OPTION_PROFILING_UI + if (presenter_) { + if (was_visible) { + presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_); + } else { + presenter_->AddUIDrawerFromUIThread(&ui_drawer_, z_order_); + } + } +#endif // XE_OPTION_PROFILING_UI + } +} + +void Profiler::SetUserIO(size_t z_order, ui::Window* window, + ui::Presenter* presenter, + ui::ImmediateDrawer* immediate_drawer) { +#if XE_OPTION_PROFILING_UI + if (presenter_ && is_visible()) { + presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_); + } + drawer_.reset(); + presenter_ = nullptr; +#endif // XE_OPTION_PROFILING_UI + + if (window_) { + if (is_visible()) { + window_->RemoveInputListener(&input_listener_); + } + window_ = nullptr; + } + if (!window) { return; } + + z_order_ = z_order; window_ = window; - drawer_ = std::make_unique(window); - window_->on_painted.AddListener([](ui::UIEvent* e) { Profiler::Present(); }); +#if XE_OPTION_PROFILING_UI + if (presenter && immediate_drawer) { + presenter_ = presenter; + drawer_ = std::make_unique(immediate_drawer); + } +#endif // XE_OPTION_PROFILING_UI - // Pass through mouse events. - window_->on_mouse_down.AddListener([](ui::MouseEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnMouseDown(e->button() == ui::MouseEvent::Button::kLeft, - e->button() == ui::MouseEvent::Button::kRight); - e->set_handled(true); - window_->Invalidate(); + if (is_visible()) { + window_->AddInputListener(&input_listener_, z_order_); +#if XE_OPTION_PROFILING_UI + if (presenter_) { + presenter_->AddUIDrawerFromUIThread(&ui_drawer_, z_order_); } - }); - window_->on_mouse_up.AddListener([](ui::MouseEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnMouseUp(); - e->set_handled(true); - window_->Invalidate(); - } - }); - window_->on_mouse_move.AddListener([](ui::MouseEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnMouseMove(e->x(), e->y()); - e->set_handled(true); - window_->Invalidate(); - } - }); - window_->on_mouse_wheel.AddListener([](ui::MouseEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnMouseWheel(e->x(), e->y(), -e->dy()); - e->set_handled(true); - window_->Invalidate(); - } - }); - - // Watch for toggle/mode keys and such. - window_->on_key_down.AddListener([](ui::KeyEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnKeyDown(e->virtual_key()); - e->set_handled(true); - window_->Invalidate(); - } - }); - window_->on_key_up.AddListener([](ui::KeyEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnKeyUp(e->virtual_key()); - e->set_handled(true); - window_->Invalidate(); - } - }); +#endif // XE_OPTION_PROFILING_UI + } +} + +void Profiler::Flip() { + MicroProfileFlip(); + // This can be called from non-UI threads, so not trying to access the drawer + // to trigger redraw here as it's owned and managed exclusively by the UI + // thread. Relying on continuous painting currently. } -void Profiler::Present() { - SCOPE_profile_cpu_f("internal"); #if XE_OPTION_PROFILING_UI - if (!window_ || !drawer_) { +void Profiler::ProfilerUIDrawer::Draw(ui::UIDrawContext& ui_draw_context) { + if (!window_ || !presenter_ || !drawer_) { return; } - drawer_->Begin(); - MicroProfileDraw(window_->scaled_width(), window_->scaled_height()); + SCOPE_profile_cpu_f("internal"); + uint32_t coordinate_space_width = dpi_scaling_ + ? window_->GetActualLogicalWidth() + : window_->GetActualPhysicalWidth(); + uint32_t coordinate_space_height = dpi_scaling_ + ? window_->GetActualLogicalHeight() + : window_->GetActualPhysicalHeight(); + drawer_->Begin(ui_draw_context, coordinate_space_width, + coordinate_space_height); + MicroProfileDraw(coordinate_space_width, coordinate_space_height); drawer_->End(); -#endif // XE_OPTION_PROFILING_UI + // Continuous repaint. + if (is_visible()) { + presenter_->RequestUIPaintFromUIThread(); + } } +#endif // XE_OPTION_PROFILING_UI -void Profiler::Flip() { MicroProfileFlip(); } +#if XE_OPTION_PROFILING_UI +void Profiler::SetMousePosition(int32_t x, int32_t y, int32_t wheel_delta) { + if (!window_) { + return; + } + if (dpi_scaling_) { + x = window_->PositionToLogical(x); + y = window_->PositionToLogical(y); + } + MicroProfileMousePosition(uint32_t(std::max(int32_t(0), x)), + uint32_t(std::max(int32_t(0), y)), wheel_delta); +} +#endif // XE_OPTION_PROFILING_UI + +void Profiler::PostInputEvent() { + // The profiler can be hidden from within the profiler (Mode > Off). + if (!is_visible()) { + window_->RemoveInputListener(&input_listener_); +#if XE_OPTION_PROFILING_UI + if (presenter_) { + presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_); + } +#endif // XE_OPTION_PROFILING_UI + return; + } + // Relying on continuous painting currently, no need to request drawing. +} #else @@ -262,16 +341,11 @@ void Profiler::Shutdown() {} uint32_t Profiler::GetColor(const char* str) { return 0; } void Profiler::ThreadEnter(const char* name) {} void Profiler::ThreadExit() {} -bool Profiler::OnKeyDown(ui::VirtualKey virtual_key) { return false; } -bool Profiler::OnKeyUp(ui::VirtualKey virtual_key) { return false; } -void Profiler::OnMouseDown(bool left_button, bool right_button) {} -void Profiler::OnMouseUp() {} -void Profiler::OnMouseMove(int x, int y) {} -void Profiler::OnMouseWheel(int x, int y, int dy) {} void Profiler::ToggleDisplay() {} void Profiler::TogglePause() {} -void Profiler::set_window(ui::Window* window) {} -void Profiler::Present() {} +void Profiler::SetUserIO(size_t z_order, ui::Window* window, + ui::Presenter* presenter, + ui::ImmediateDrawer* immediate_drawer) {} void Profiler::Flip() {} #endif // XE_OPTION_PROFILING @@ -310,7 +384,7 @@ void MicroProfileDrawText(int nX, int nY, uint32_t nColor, const char* pText, if (!drawer) { return; } - drawer->DrawText(nX, nY, nColor, pText, nLen); + drawer->DrawTextString(nX, nY, nColor, pText, nLen); } #endif // XE_OPTION_PROFILING_UI diff --git a/src/xenia/base/profiling.h b/src/xenia/base/profiling.h index a55600d7e..24b875967 100644 --- a/src/xenia/base/profiling.h +++ b/src/xenia/base/profiling.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,10 +10,15 @@ #ifndef XENIA_BASE_PROFILING_H_ #define XENIA_BASE_PROFILING_H_ +#include +#include #include +#include "xenia/base/platform.h" #include "xenia/base/string.h" +#include "xenia/ui/ui_drawer.h" #include "xenia/ui/virtual_key.h" +#include "xenia/ui/window_listener.h" #if XE_PLATFORM_WIN32 #define XE_OPTION_PROFILING 1 @@ -30,7 +35,9 @@ namespace xe { namespace ui { +class ImmediateDrawer; class MicroprofileDrawer; +class Presenter; class Window; } // namespace ui } // namespace xe @@ -172,27 +179,65 @@ class Profiler { // Deactivates the calling thread for profiling. static void ThreadExit(); - static bool OnKeyDown(ui::VirtualKey virtual_key); - static bool OnKeyUp(ui::VirtualKey virtual_key); - static void OnMouseDown(bool left_button, bool right_button); - static void OnMouseUp(); - static void OnMouseMove(int x, int y); - static void OnMouseWheel(int x, int y, int dy); static void ToggleDisplay(); static void TogglePause(); - // Initializes input and drawing with the given display. - static void set_window(ui::Window* window); - // Gets the current display, if any. - static ui::MicroprofileDrawer* drawer() { return drawer_.get(); } + // Initializes input for the given window and drawing for the given presenter + // and immediate drawer. + static void SetUserIO(size_t z_order, ui::Window* window, + ui::Presenter* presenter, + ui::ImmediateDrawer* immediate_drawer); + // Gets the current drawer, if any. + static ui::MicroprofileDrawer* drawer() { +#if XE_OPTION_PROFILING_UI + return drawer_.get(); +#else + return nullptr; +#endif + } // Presents the profiler to the bound display, if any. - static void Present(); + static void Present(ui::UIDrawContext& ui_draw_context); // Starts a new frame on the profiler static void Flip(); private: +#if XE_OPTION_PROFILING + class ProfilerWindowInputListener final : public ui::WindowInputListener { + public: + void OnKeyDown(ui::KeyEvent& e) override; + void OnKeyUp(ui::KeyEvent& e) override; +#if XE_OPTION_PROFILING_UI + void OnMouseDown(ui::MouseEvent& e) override; + void OnMouseMove(ui::MouseEvent& e) override; + void OnMouseUp(ui::MouseEvent& e) override; + void OnMouseWheel(ui::MouseEvent& e) override; +#endif // XE_OPTION_PROFILING_UI + }; + // For now, no need for OnDpiChanged in a WindowListener because redrawing is + // done continuously. + +#if XE_OPTION_PROFILING_UI + class ProfilerUIDrawer final : public ui::UIDrawer { + public: + void Draw(ui::UIDrawContext& context) override; + }; +#endif // XE_OPTION_PROFILING_UI + +#if XE_OPTION_PROFILING_UI + static void SetMousePosition(int32_t x, int32_t y, int32_t wheel_delta); +#endif // XE_OPTION_PROFILING_UI + static void PostInputEvent(); + + static ProfilerWindowInputListener input_listener_; + static size_t z_order_; static ui::Window* window_; +#if XE_OPTION_PROFILING_UI + static ProfilerUIDrawer ui_drawer_; + static ui::Presenter* presenter_; static std::unique_ptr drawer_; + static bool dpi_scaling_; +#endif // XE_OPTION_PROFILING_UI +#endif // XE_OPTION_PROFILING }; } // namespace xe diff --git a/src/xenia/base/string_buffer.cc b/src/xenia/base/string_buffer.cc index 050ddf9d8..b3a9270a8 100644 --- a/src/xenia/base/string_buffer.cc +++ b/src/xenia/base/string_buffer.cc @@ -13,12 +13,15 @@ #include #include "xenia/base/assert.h" +#include "xenia/base/literals.h" #include "xenia/base/math.h" namespace xe { +using namespace xe::literals; + StringBuffer::StringBuffer(size_t initial_capacity) { - buffer_capacity_ = std::max(initial_capacity, static_cast(16 * 1024)); + buffer_capacity_ = std::max(initial_capacity, static_cast(16_KiB)); buffer_ = reinterpret_cast(std::malloc(buffer_capacity_)); assert_not_null(buffer_); buffer_[0] = 0; @@ -40,7 +43,7 @@ void StringBuffer::Grow(size_t additional_length) { } size_t old_capacity = buffer_capacity_; size_t new_capacity = - std::max(xe::round_up(buffer_offset_ + additional_length, 16 * 1024), + std::max(xe::round_up(buffer_offset_ + additional_length, 16_KiB), old_capacity * 2); auto new_buffer = std::realloc(buffer_, new_capacity); assert_not_null(new_buffer); diff --git a/src/xenia/base/string_util.h b/src/xenia/base/string_util.h index 3c73f9c65..09575ff56 100644 --- a/src/xenia/base/string_util.h +++ b/src/xenia/base/string_util.h @@ -134,7 +134,7 @@ inline std::string to_hex_string(double value) { } inline std::string to_hex_string(const vec128_t& value) { - return fmt::format("[{:08X} {:08X} {:08X} {:08X} {:08X}]", value.u32[0], + return fmt::format("[{:08X} {:08X} {:08X} {:08X}]", value.u32[0], value.u32[1], value.u32[2], value.u32[3]); } diff --git a/src/xenia/base/system.h b/src/xenia/base/system.h index 4bd0eac2b..b77bdbc69 100644 --- a/src/xenia/base/system.h +++ b/src/xenia/base/system.h @@ -13,10 +13,17 @@ #include #include +#include "xenia/base/platform.h" #include "xenia/base/string.h" namespace xe { +#if XE_PLATFORM_ANDROID +bool InitializeAndroidSystemForApplicationContext(); +void ShutdownAndroidSystem(); +#endif + +// The URL must include the protocol. void LaunchWebBrowser(const std::string_view url); void LaunchFileExplorer(const std::filesystem::path& path); diff --git a/src/xenia/base/system_android.cc b/src/xenia/base/system_android.cc new file mode 100644 index 000000000..25c14a7bc --- /dev/null +++ b/src/xenia/base/system_android.cc @@ -0,0 +1,297 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" +#include "xenia/base/main_android.h" +#include "xenia/base/system.h" + +namespace xe { + +// To store method and field IDs persistently, global references to the classes +// are required to prevent the classes from being unloaded and reloaded, +// potentially changing the IDs. + +static jclass android_system_application_context_class_ = nullptr; +static jmethodID android_system_application_context_start_activity_ = nullptr; + +static jclass android_system_uri_class_ = nullptr; +static jmethodID android_system_uri_parse_ = nullptr; + +static jclass android_system_intent_class_ = nullptr; +static jmethodID android_system_intent_init_action_uri_ = nullptr; +static jmethodID android_system_intent_add_flags_ = nullptr; +static jobject android_system_intent_action_view_ = nullptr; +static jint android_system_intent_flag_activity_new_task_; + +static bool android_system_initialized_ = false; + +bool InitializeAndroidSystemForApplicationContext() { + assert_false(android_system_initialized_); + + JNIEnv* jni_env = GetAndroidThreadJniEnv(); + if (!jni_env) { + return false; + } + jobject application_context = xe::GetAndroidApplicationContext(); + if (!application_context) { + return false; + } + + // Application context. + { + { + jclass application_context_class_local_ref = + jni_env->GetObjectClass(application_context); + if (!application_context_class_local_ref) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to get the " + "class of the application context"); + ShutdownAndroidSystem(); + return false; + } + android_system_application_context_class_ = + reinterpret_cast(jni_env->NewGlobalRef( + reinterpret_cast(application_context_class_local_ref))); + jni_env->DeleteLocalRef(application_context_class_local_ref); + } + if (!android_system_application_context_class_) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to create a " + "global reference to the class of the application context"); + ShutdownAndroidSystem(); + return false; + } + bool application_context_ids_obtained = true; + application_context_ids_obtained &= + (android_system_application_context_start_activity_ = + jni_env->GetMethodID(android_system_application_context_class_, + "startActivity", + "(Landroid/content/Intent;)V")) != nullptr; + if (!application_context_ids_obtained) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to get the " + "application context class IDs"); + ShutdownAndroidSystem(); + return false; + } + } + + // URI. + { + { + jclass uri_class_local_ref = jni_env->FindClass("android/net/Uri"); + if (!uri_class_local_ref) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to find the " + "URI class"); + ShutdownAndroidSystem(); + return false; + } + android_system_uri_class_ = + reinterpret_cast(jni_env->NewGlobalRef( + reinterpret_cast(uri_class_local_ref))); + jni_env->DeleteLocalRef(uri_class_local_ref); + } + if (!android_system_uri_class_) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to create a " + "global reference to the URI class"); + ShutdownAndroidSystem(); + return false; + } + bool uri_ids_obtained = true; + uri_ids_obtained &= + (android_system_uri_parse_ = jni_env->GetStaticMethodID( + android_system_uri_class_, "parse", + "(Ljava/lang/String;)Landroid/net/Uri;")) != nullptr; + if (!uri_ids_obtained) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to get the URI " + "class IDs"); + ShutdownAndroidSystem(); + return false; + } + } + + // Intent. + { + { + jclass intent_class_local_ref = + jni_env->FindClass("android/content/Intent"); + if (!intent_class_local_ref) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to find the " + "intent class"); + ShutdownAndroidSystem(); + return false; + } + android_system_intent_class_ = + reinterpret_cast(jni_env->NewGlobalRef( + reinterpret_cast(intent_class_local_ref))); + jni_env->DeleteLocalRef(intent_class_local_ref); + } + if (!android_system_intent_class_) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to create a " + "global reference to the intent class"); + ShutdownAndroidSystem(); + return false; + } + bool intent_ids_obtained = true; + jfieldID intent_action_view_id; + intent_ids_obtained &= (intent_action_view_id = jni_env->GetStaticFieldID( + android_system_intent_class_, "ACTION_VIEW", + "Ljava/lang/String;")) != nullptr; + jfieldID intent_flag_activity_new_task_id; + intent_ids_obtained &= + (intent_flag_activity_new_task_id = jni_env->GetStaticFieldID( + android_system_intent_class_, "FLAG_ACTIVITY_NEW_TASK", "I")) != + nullptr; + intent_ids_obtained &= + (android_system_intent_init_action_uri_ = jni_env->GetMethodID( + android_system_intent_class_, "", + "(Ljava/lang/String;Landroid/net/Uri;)V")) != nullptr; + intent_ids_obtained &= + (android_system_intent_add_flags_ = + jni_env->GetMethodID(android_system_intent_class_, "addFlags", + "(I)Landroid/content/Intent;")) != nullptr; + if (!intent_ids_obtained) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to get the " + "intent class IDs"); + ShutdownAndroidSystem(); + return false; + } + { + jobject intent_action_view_local_ref = jni_env->GetStaticObjectField( + android_system_intent_class_, intent_action_view_id); + if (!intent_action_view_local_ref) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to get the " + "intent view action string"); + ShutdownAndroidSystem(); + return false; + } + android_system_intent_action_view_ = + jni_env->NewGlobalRef(intent_action_view_local_ref); + jni_env->DeleteLocalRef(intent_action_view_local_ref); + if (!android_system_intent_action_view_) { + XELOGE( + "InitializeAndroidSystemForApplicationContext: Failed to create a " + "global reference to the intent view action string"); + ShutdownAndroidSystem(); + return false; + } + } + android_system_intent_flag_activity_new_task_ = jni_env->GetStaticIntField( + android_system_intent_class_, intent_flag_activity_new_task_id); + } + + android_system_initialized_ = true; + return true; +} + +void ShutdownAndroidSystem() { + // May be called from InitializeAndroidSystemForApplicationContext as well. + android_system_initialized_ = false; + android_system_intent_add_flags_ = nullptr; + android_system_intent_init_action_uri_ = nullptr; + android_system_uri_parse_ = nullptr; + android_system_application_context_start_activity_ = nullptr; + JNIEnv* jni_env = GetAndroidThreadJniEnv(); + if (jni_env) { + if (android_system_intent_action_view_) { + jni_env->DeleteGlobalRef(android_system_intent_action_view_); + } + if (android_system_intent_class_) { + jni_env->DeleteGlobalRef(android_system_intent_class_); + } + if (android_system_uri_class_) { + jni_env->DeleteGlobalRef(android_system_uri_class_); + } + if (android_system_application_context_class_) { + jni_env->DeleteGlobalRef(android_system_application_context_class_); + } + } + android_system_intent_action_view_ = nullptr; + android_system_intent_class_ = nullptr; + android_system_uri_class_ = nullptr; + android_system_application_context_class_ = nullptr; +} + +void LaunchWebBrowser(const std::string_view url) { + if (!android_system_initialized_) { + return; + } + JNIEnv* jni_env = GetAndroidThreadJniEnv(); + if (!jni_env) { + return; + } + jobject application_context = GetAndroidApplicationContext(); + if (!application_context) { + return; + } + + jstring uri_string = jni_env->NewStringUTF(std::string(url).c_str()); + if (!uri_string) { + XELOGE("LaunchWebBrowser: Failed to create the URI string"); + return; + } + jobject uri = jni_env->CallStaticObjectMethod( + android_system_uri_class_, android_system_uri_parse_, uri_string); + jni_env->DeleteLocalRef(uri_string); + if (!uri) { + XELOGE("LaunchWebBrowser: Failed to parse the URI"); + return; + } + jobject intent = jni_env->NewObject(android_system_intent_class_, + android_system_intent_init_action_uri_, + android_system_intent_action_view_, uri); + jni_env->DeleteLocalRef(uri); + if (!intent) { + XELOGE("LaunchWebBrowser: Failed to create the intent"); + return; + } + // Start a new task - the user may want to be able to switch between the + // emulator and the newly opened web browser, without having to quit the web + // browser to return to the emulator. Also, since the application context, not + // the activity, is used, the new task flag is required. + { + jobject intent_add_flags_result_local_ref = jni_env->CallObjectMethod( + intent, android_system_intent_add_flags_, + android_system_intent_flag_activity_new_task_); + if (intent_add_flags_result_local_ref) { + jni_env->DeleteLocalRef(intent_add_flags_result_local_ref); + } + } + jni_env->CallVoidMethod(application_context, + android_system_application_context_start_activity_, + intent); + jni_env->DeleteLocalRef(intent); +} + +void LaunchFileExplorer(const std::filesystem::path& path) { assert_always(); } + +void ShowSimpleMessageBox(SimpleMessageBoxType type, std::string_view message) { + // TODO(Triang3l): Likely not needed much at all. ShowSimpleMessageBox is a + // concept pretty unfriendly to platforms like Android because it's blocking, + // and because it can be called from threads other than the UI thread. In the + // normal execution flow, dialogs should preferably be asynchronous, and used + // only in the UI thread. However, non-blocking messages may be good for error + // reporting - investigate the usage of Toasts with respect to threads, and + // aborting the process immediately after showing a Toast. For a Toast, the + // Java VM for the calling thread is needed. +} + +} // namespace xe diff --git a/src/xenia/base/system_linux.cc b/src/xenia/base/system_gnulinux.cc similarity index 100% rename from src/xenia/base/system_linux.cc rename to src/xenia/base/system_gnulinux.cc diff --git a/src/xenia/base/testing/memory_test.cc b/src/xenia/base/testing/memory_test.cc index f78d9c3bb..3f3c1f963 100644 --- a/src/xenia/base/testing/memory_test.cc +++ b/src/xenia/base/testing/memory_test.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -14,6 +14,8 @@ #include "xenia/base/clock.h" +#include + namespace xe { namespace base { namespace test { @@ -113,6 +115,24 @@ TEST_CASE("copy_and_swap_16_unaligned", "[copy_and_swap]") { REQUIRE(c[2] == 0xAB89); REQUIRE(c[3] == 0xEFCD); + { + constexpr size_t count = 100; + std::array src{}; + std::array dst{}; + for (size_t i = 0; i < src.size(); ++i) { + src[i] = static_cast(i) + 1; // no zero in array + } + copy_and_swap_16_unaligned(dst.data(), src.data(), count); + for (size_t i = 0; i < src.size(); i += 2) { + // Check src is untouched + REQUIRE(static_cast(src[i + 0]) == i + 1); + REQUIRE(static_cast(src[i + 1]) == i + 2); + // Check swapped bytes + REQUIRE(static_cast(dst[i]) == static_cast(src[i + 1])); + REQUIRE(static_cast(dst[i + 1]) == static_cast(src[i])); + } + } + uint64_t e; copy_and_swap_16_unaligned(&e, d, 4); REQUIRE(e == 0xEFCDAB8967452301); @@ -221,6 +241,32 @@ TEST_CASE("copy_and_swap_32_unaligned", "[copy_and_swap]") { REQUIRE(c[2] == 0xEDEE87E8); REQUIRE(c[3] == 0x994151D8); + { + constexpr size_t count = 17; + std::array src{}; + std::array dst{}; + for (size_t i = 0; i < src.size(); ++i) { + src[i] = static_cast(i) + 1; // no zero in array + } + copy_and_swap_32_unaligned(dst.data(), src.data(), count); + for (size_t i = 0; i < src.size(); i += 4) { + // Check src is untouched + REQUIRE(static_cast(src[i + 0]) == i + 1); + REQUIRE(static_cast(src[i + 1]) == i + 2); + REQUIRE(static_cast(src[i + 2]) == i + 3); + REQUIRE(static_cast(src[i + 3]) == i + 4); + // Check swapped bytes + REQUIRE(static_cast(dst[i + 0]) == + static_cast(src[i + 3])); + REQUIRE(static_cast(dst[i + 1]) == + static_cast(src[i + 2])); + REQUIRE(static_cast(dst[i + 2]) == + static_cast(src[i + 1])); + REQUIRE(static_cast(dst[i + 3]) == + static_cast(src[i + 0])); + } + } + uint64_t e; copy_and_swap_32_unaligned(&e, d, 2); REQUIRE(e == 0xEFCDAB8967452301); @@ -408,13 +454,56 @@ TEST_CASE("copy_and_swap_64_unaligned", "[copy_and_swap]") { } TEST_CASE("copy_and_swap_16_in_32_aligned", "[copy_and_swap]") { - // TODO(bwrsandman): test once properly understood. - REQUIRE(true == true); + constexpr size_t count = 17; + alignas(16) std::array src{}; + alignas(16) std::array dst{}; + + // Check alignment (if this fails, adjust allocation) + REQUIRE((reinterpret_cast(src.data()) & 0xF) == 0); + REQUIRE((reinterpret_cast(dst.data()) & 0xF) == 0); + + for (size_t i = 0; i < src.size(); ++i) { + src[i] = static_cast(i) + 1; // no zero in array + } + + copy_and_swap_16_in_32_aligned(dst.data(), src.data(), count); + + for (size_t i = 0; i < src.size(); i += 4) { + // Check src is untouched + REQUIRE(static_cast(src[i + 0]) == i + 1); + REQUIRE(static_cast(src[i + 1]) == i + 2); + REQUIRE(static_cast(src[i + 2]) == i + 3); + REQUIRE(static_cast(src[i + 3]) == i + 4); + // Check swapped bytes + REQUIRE(static_cast(dst[i + 0]) == static_cast(src[i + 2])); + REQUIRE(static_cast(dst[i + 1]) == static_cast(src[i + 3])); + REQUIRE(static_cast(dst[i + 2]) == static_cast(src[i + 0])); + REQUIRE(static_cast(dst[i + 3]) == static_cast(src[i + 1])); + } } TEST_CASE("copy_and_swap_16_in_32_unaligned", "[copy_and_swap]") { - // TODO(bwrsandman): test once properly understood. - REQUIRE(true == true); + constexpr size_t count = 17; + std::array src{}; + std::array dst{}; + for (size_t i = 0; i < src.size(); ++i) { + src[i] = static_cast(i) + 1; // no zero in array + } + + copy_and_swap_16_in_32_unaligned(dst.data(), src.data(), count); + + for (size_t i = 0; i < src.size(); i += 4) { + // Check src is untouched + REQUIRE(static_cast(src[i + 0]) == i + 1); + REQUIRE(static_cast(src[i + 1]) == i + 2); + REQUIRE(static_cast(src[i + 2]) == i + 3); + REQUIRE(static_cast(src[i + 3]) == i + 4); + // Check swapped bytes + REQUIRE(static_cast(dst[i + 0]) == static_cast(src[i + 2])); + REQUIRE(static_cast(dst[i + 1]) == static_cast(src[i + 3])); + REQUIRE(static_cast(dst[i + 2]) == static_cast(src[i + 0])); + REQUIRE(static_cast(dst[i + 3]) == static_cast(src[i + 1])); + } } TEST_CASE("create_and_close_file_mapping", "Virtual Memory Mapping") { diff --git a/src/xenia/base/testing/threading_test.cc b/src/xenia/base/testing/threading_test.cc index 4bb87a518..d1380d602 100644 --- a/src/xenia/base/testing/threading_test.cc +++ b/src/xenia/base/testing/threading_test.cc @@ -824,7 +824,7 @@ TEST_CASE("Create and Run Thread", "[thread]") { } SECTION("16kb stack size") { - params.stack_size = 16 * 1024 * 1024; + params.stack_size = 16_MiB; thread = Thread::Create(params, [] { Thread::Exit(-1); FAIL("Function must not return"); diff --git a/src/xenia/base/threading.h b/src/xenia/base/threading.h index 520c2d531..63a63b4d4 100644 --- a/src/xenia/base/threading.h +++ b/src/xenia/base/threading.h @@ -25,11 +25,14 @@ #include #include "xenia/base/assert.h" +#include "xenia/base/literals.h" #include "xenia/base/platform.h" namespace xe { namespace threading { +using namespace xe::literals; + #if XE_PLATFORM_ANDROID void AndroidInitialize(); void AndroidShutdown(); @@ -368,7 +371,7 @@ struct ThreadPriority { class Thread : public WaitHandle { public: struct CreationParameters { - size_t stack_size = 4 * 1024 * 1024; + size_t stack_size = 4_MiB; bool create_suspended = false; int32_t initial_priority = 0; }; diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 05fc616b7..813758a4b 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -14,6 +14,7 @@ #include "xenia/base/platform.h" #include +#include #include #include #include @@ -28,7 +29,6 @@ #if XE_PLATFORM_ANDROID #include -#include #include "xenia/base/main_android.h" #include "xenia/base/string_util.h" @@ -128,11 +128,7 @@ uint32_t current_thread_system_id() { } void MaybeYield() { -#if XE_PLATFORM_ANDROID sched_yield(); -#else - pthread_yield(); -#endif __sync_synchronize(); } diff --git a/src/xenia/base/vec128.cc b/src/xenia/base/vec128.cc index 70562dda1..5d91f7b5f 100644 --- a/src/xenia/base/vec128.cc +++ b/src/xenia/base/vec128.cc @@ -8,11 +8,13 @@ */ #include +#include #include #include "third_party/fmt/include/fmt/format.h" #include "xenia/base/math.h" #include "xenia/base/platform.h" +#include "xenia/base/string_util.h" #include "xenia/base/vec128.h" namespace xe { @@ -21,4 +23,9 @@ std::string to_string(const vec128_t& value) { return fmt::format("({}, {}, {}, {})", value.x, value.y, value.z, value.w); } +std::ostream& operator<<(std::ostream& os, const vec128_t& value) { + os << string_util::to_hex_string(value); + return os; +} + } // namespace xe diff --git a/src/xenia/base/vec128.h b/src/xenia/base/vec128.h index cfba512a0..c9fc4cc13 100644 --- a/src/xenia/base/vec128.h +++ b/src/xenia/base/vec128.h @@ -257,6 +257,8 @@ static inline vec128_t vec128b(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, std::string to_string(const vec128_t& value); +std::ostream& operator<<(std::ostream& os, const vec128_t& value); + } // namespace xe #endif // XENIA_BASE_VEC128_H_ diff --git a/src/xenia/config.cc b/src/xenia/config.cc index be19bccda..dcdc5ac2b 100644 --- a/src/xenia/config.cc +++ b/src/xenia/config.cc @@ -105,6 +105,10 @@ void ReadGameConfig(const std::filesystem::path& file_path) { } void SaveConfig() { + if (config_path.empty()) { + return; + } + // All cvar defaults have been updated on loading - store the current date. auto defaults_date_cvar = dynamic_cast*>(cv::cv_defaults_date); diff --git a/src/xenia/config.h b/src/xenia/config.h index 63ef265d5..2271cea6c 100644 --- a/src/xenia/config.h +++ b/src/xenia/config.h @@ -15,6 +15,7 @@ namespace config { void SetupConfig(const std::filesystem::path& config_folder); void LoadGameConfig(const std::string_view title_id); +void SaveConfig(); } // namespace config #endif // XENIA_CONFIG_H_ diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc index 130d84456..1da4ba9f3 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.cc +++ b/src/xenia/cpu/backend/x64/x64_backend.cc @@ -26,10 +26,24 @@ #include "xenia/cpu/processor.h" #include "xenia/cpu/stack_walker.h" -DEFINE_bool( - use_haswell_instructions, true, - "Uses the AVX2/FMA/etc instructions on Haswell processors when available.", - "CPU"); +DEFINE_int32(x64_extension_mask, -1, + "Allow the detection and utilization of specific instruction set " + "features.\n" + " 0 = x86_64 + AVX1\n" + " 1 = AVX2\n" + " 2 = FMA\n" + " 4 = LZCNT\n" + " 8 = BMI1\n" + " 16 = BMI2\n" + " 32 = F16C\n" + " 64 = Movbe\n" + " 128 = GFNI\n" + " 256 = AVX512F\n" + " 512 = AVX512VL\n" + " 1024 = AVX512BW\n" + " 2048 = AVX512DQ\n" + " -1 = Detect and utilize all possible processor features\n", + "x64"); namespace xe { namespace cpu { @@ -84,7 +98,7 @@ bool X64Backend::Initialize(Processor* processor) { } // Need movbe to do advanced LOAD/STORE tricks. - if (cvars::use_haswell_instructions) { + if (cvars::x64_extension_mask & kX64EmitMovbe) { machine_info_.supports_extended_load_store = cpu.has(Xbyak::util::Cpu::tMOVBE); } else { diff --git a/src/xenia/cpu/backend/x64/x64_backend.h b/src/xenia/cpu/backend/x64/x64_backend.h index d3036e875..4cb69e040 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.h +++ b/src/xenia/cpu/backend/x64/x64_backend.h @@ -15,7 +15,7 @@ #include "xenia/base/cvar.h" #include "xenia/cpu/backend/backend.h" -DECLARE_bool(use_haswell_instructions); +DECLARE_int32(x64_extension_mask); namespace xe { class Exception; diff --git a/src/xenia/cpu/backend/x64/x64_code_cache.cc b/src/xenia/cpu/backend/x64/x64_code_cache.cc index beb715661..2b49e14a9 100644 --- a/src/xenia/cpu/backend/x64/x64_code_cache.cc +++ b/src/xenia/cpu/backend/x64/x64_code_cache.cc @@ -20,6 +20,7 @@ #include "third_party/fmt/include/fmt/format.h" #include "xenia/base/assert.h" #include "xenia/base/clock.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" @@ -31,6 +32,8 @@ namespace cpu { namespace backend { namespace x64 { +using namespace xe::literals; + X64CodeCache::X64CodeCache() = default; X64CodeCache::~X64CodeCache() { @@ -227,7 +230,7 @@ void X64CodeCache::PlaceGuestCode(uint32_t guest_address, void* machine_code, old_commit_mark = generated_code_commit_mark_; if (high_mark <= old_commit_mark) break; - new_commit_mark = old_commit_mark + 16 * 1024 * 1024; + new_commit_mark = old_commit_mark + 16_MiB; if (generated_code_execute_base_ == generated_code_write_base_) { xe::memory::AllocFixed(generated_code_execute_base_, new_commit_mark, xe::memory::AllocationType::kCommit, @@ -310,7 +313,7 @@ uint32_t X64CodeCache::PlaceData(const void* data, size_t length) { old_commit_mark = generated_code_commit_mark_; if (high_mark <= old_commit_mark) break; - new_commit_mark = old_commit_mark + 16 * 1024 * 1024; + new_commit_mark = old_commit_mark + 16_MiB; if (generated_code_execute_base_ == generated_code_write_base_) { xe::memory::AllocFixed(generated_code_execute_base_, new_commit_mark, xe::memory::AllocationType::kCommit, diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc index f3419bb05..eda6be614 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.cc +++ b/src/xenia/cpu/backend/x64/x64_emitter.cc @@ -18,6 +18,7 @@ #include "xenia/base/assert.h" #include "xenia/base/atomic.h" #include "xenia/base/debugging.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" @@ -50,8 +51,9 @@ namespace x64 { using xe::cpu::hir::HIRBuilder; using xe::cpu::hir::Instr; +using namespace xe::literals; -static const size_t kMaxCodeSize = 1 * 1024 * 1024; +static const size_t kMaxCodeSize = 1_MiB; static const size_t kStashOffset = 32; // static const size_t kStashOffsetHigh = 32 + 32; @@ -72,21 +74,31 @@ X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator) backend_(backend), code_cache_(backend->code_cache()), allocator_(allocator) { - if (cvars::use_haswell_instructions) { - feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tAVX2) ? kX64EmitAVX2 : 0; - feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tFMA) ? kX64EmitFMA : 0; - feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tLZCNT) ? kX64EmitLZCNT : 0; - feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tBMI2) ? kX64EmitBMI2 : 0; - feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tF16C) ? kX64EmitF16C : 0; - feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tMOVBE) ? kX64EmitMovbe : 0; - } - if (!cpu_.has(Xbyak::util::Cpu::tAVX)) { xe::FatalError( "Your CPU does not support AVX, which is required by Xenia. See the " "FAQ for system requirements at https://xenia.jp"); return; } + +#define TEST_EMIT_FEATURE(emit, ext) \ + if ((cvars::x64_extension_mask & emit) == emit) { \ + feature_flags_ |= (cpu_.has(ext) ? emit : 0); \ + } + + TEST_EMIT_FEATURE(kX64EmitAVX2, Xbyak::util::Cpu::tAVX2); + TEST_EMIT_FEATURE(kX64EmitFMA, Xbyak::util::Cpu::tFMA); + TEST_EMIT_FEATURE(kX64EmitLZCNT, Xbyak::util::Cpu::tLZCNT); + TEST_EMIT_FEATURE(kX64EmitBMI1, Xbyak::util::Cpu::tBMI1); + TEST_EMIT_FEATURE(kX64EmitF16C, Xbyak::util::Cpu::tF16C); + TEST_EMIT_FEATURE(kX64EmitMovbe, Xbyak::util::Cpu::tMOVBE); + TEST_EMIT_FEATURE(kX64EmitGFNI, Xbyak::util::Cpu::tGFNI); + TEST_EMIT_FEATURE(kX64EmitAVX512F, Xbyak::util::Cpu::tAVX512F); + TEST_EMIT_FEATURE(kX64EmitAVX512VL, Xbyak::util::Cpu::tAVX512VL); + TEST_EMIT_FEATURE(kX64EmitAVX512BW, Xbyak::util::Cpu::tAVX512BW); + TEST_EMIT_FEATURE(kX64EmitAVX512DQ, Xbyak::util::Cpu::tAVX512DQ); + +#undef TEST_EMIT_FEATURE } X64Emitter::~X64Emitter() = default; diff --git a/src/xenia/cpu/backend/x64/x64_emitter.h b/src/xenia/cpu/backend/x64/x64_emitter.h index 4a31543b6..840e355fc 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.h +++ b/src/xenia/cpu/backend/x64/x64_emitter.h @@ -125,12 +125,23 @@ class XbyakAllocator : public Xbyak::Allocator { }; enum X64EmitterFeatureFlags { - kX64EmitAVX2 = 1 << 1, - kX64EmitFMA = 1 << 2, - kX64EmitLZCNT = 1 << 3, + kX64EmitAVX2 = 1 << 0, + kX64EmitFMA = 1 << 1, + kX64EmitLZCNT = 1 << 2, + kX64EmitBMI1 = 1 << 3, kX64EmitBMI2 = 1 << 4, kX64EmitF16C = 1 << 5, kX64EmitMovbe = 1 << 6, + kX64EmitGFNI = 1 << 7, + + kX64EmitAVX512F = 1 << 8, + kX64EmitAVX512VL = 1 << 9, + + kX64EmitAVX512BW = 1 << 10, + kX64EmitAVX512DQ = 1 << 11, + + kX64EmitAVX512Ortho = kX64EmitAVX512F | kX64EmitAVX512VL, + kX64EmitAVX512Ortho64 = kX64EmitAVX512Ortho | kX64EmitAVX512DQ }; class X64Emitter : public Xbyak::CodeGenerator { @@ -221,7 +232,7 @@ class X64Emitter : public Xbyak::CodeGenerator { Xbyak::Address StashConstantXmm(int index, const vec128_t& v); bool IsFeatureEnabled(uint32_t feature_flag) const { - return (feature_flags_ & feature_flag) != 0; + return (feature_flags_ & feature_flag) == feature_flag; } FunctionDebugInfo* debug_info() const { return debug_info_; } diff --git a/src/xenia/cpu/backend/x64/x64_seq_vector.cc b/src/xenia/cpu/backend/x64/x64_seq_vector.cc index b5a8e49a2..4daea260b 100644 --- a/src/xenia/cpu/backend/x64/x64_seq_vector.cc +++ b/src/xenia/cpu/backend/x64/x64_seq_vector.cc @@ -731,6 +731,25 @@ struct VECTOR_SHL_V128 static void EmitInt8(X64Emitter& e, const EmitArgType& i) { // TODO(benvanik): native version (with shift magic). if (i.src2.is_constant) { + if (e.IsFeatureEnabled(kX64EmitGFNI)) { + const auto& shamt = i.src2.constant(); + bool all_same = true; + for (size_t n = 0; n < 16 - n; ++n) { + if (shamt.u8[n] != shamt.u8[n + 1]) { + all_same = false; + break; + } + } + if (all_same) { + // Every count is the same, so we can use gf2p8affineqb. + const uint8_t shift_amount = shamt.u8[0] & 0b111; + const uint64_t shift_matrix = + UINT64_C(0x0102040810204080) >> (shift_amount * 8); + e.vgf2p8affineqb(i.dest, i.src1, + e.StashConstantXmm(0, vec128q(shift_matrix)), 0); + return; + } + } e.lea(e.GetNativeParam(1), e.StashConstantXmm(1, i.src2.constant())); } else { e.lea(e.GetNativeParam(1), e.StashXmm(1, i.src2)); @@ -920,6 +939,25 @@ struct VECTOR_SHR_V128 static void EmitInt8(X64Emitter& e, const EmitArgType& i) { // TODO(benvanik): native version (with shift magic). if (i.src2.is_constant) { + if (e.IsFeatureEnabled(kX64EmitGFNI)) { + const auto& shamt = i.src2.constant(); + bool all_same = true; + for (size_t n = 0; n < 16 - n; ++n) { + if (shamt.u8[n] != shamt.u8[n + 1]) { + all_same = false; + break; + } + } + if (all_same) { + // Every count is the same, so we can use gf2p8affineqb. + const uint8_t shift_amount = shamt.u8[0] & 0b111; + const uint64_t shift_matrix = UINT64_C(0x0102040810204080) + << (shift_amount * 8); + e.vgf2p8affineqb(i.dest, i.src1, + e.StashConstantXmm(0, vec128q(shift_matrix)), 0); + return; + } + } e.lea(e.GetNativeParam(1), e.StashConstantXmm(1, i.src2.constant())); } else { e.lea(e.GetNativeParam(1), e.StashXmm(1, i.src2)); @@ -1084,6 +1122,27 @@ struct VECTOR_SHA_V128 static void EmitInt8(X64Emitter& e, const EmitArgType& i) { // TODO(benvanik): native version (with shift magic). if (i.src2.is_constant) { + if (e.IsFeatureEnabled(kX64EmitGFNI)) { + const auto& shamt = i.src2.constant(); + bool all_same = true; + for (size_t n = 0; n < 16 - n; ++n) { + if (shamt.u8[n] != shamt.u8[n + 1]) { + all_same = false; + break; + } + } + if (all_same) { + // Every count is the same, so we can use gf2p8affineqb. + const uint8_t shift_amount = shamt.u8[0] & 0b111; + const uint64_t shift_matrix = + (UINT64_C(0x0102040810204080) << (shift_amount * 8)) | + (UINT64_C(0x8080808080808080) >> (64 - shift_amount * 8)); + ; + e.vgf2p8affineqb(i.dest, i.src1, + e.StashConstantXmm(0, vec128q(shift_matrix)), 0); + return; + } + } e.lea(e.GetNativeParam(1), e.StashConstantXmm(1, i.src2.constant())); } else { e.lea(e.GetNativeParam(1), e.StashXmm(1, i.src2)); diff --git a/src/xenia/cpu/backend/x64/x64_sequences.cc b/src/xenia/cpu/backend/x64/x64_sequences.cc index 37a05c60b..62f6e9a3f 100644 --- a/src/xenia/cpu/backend/x64/x64_sequences.cc +++ b/src/xenia/cpu/backend/x64/x64_sequences.cc @@ -2627,6 +2627,115 @@ struct AND_V128 : Sequence> { }; EMITTER_OPCODE_TABLE(OPCODE_AND, AND_I8, AND_I16, AND_I32, AND_I64, AND_V128); +// ============================================================================ +// OPCODE_AND_NOT +// ============================================================================ +template +void EmitAndNotXX(X64Emitter& e, const ARGS& i) { + if (i.src1.is_constant) { + if (i.src2.is_constant) { + // Both constants. + e.mov(i.dest, i.src1.constant() & ~i.src2.constant()); + } else { + // src1 constant. + + // `and` instruction only supports up to 32-bit immediate constants + // 64-bit constants will need a temp register + if (i.dest.reg().getBit() == 64) { + auto temp = GetTempReg(e); + e.mov(temp, i.src1.constant()); + + if (e.IsFeatureEnabled(kX64EmitBMI1)) { + if (i.dest.reg().getBit() == 64) { + e.andn(i.dest.reg().cvt64(), i.src2.reg().cvt64(), temp.cvt64()); + } else { + e.andn(i.dest.reg().cvt32(), i.src2.reg().cvt32(), temp.cvt32()); + } + } else { + e.mov(i.dest, i.src2); + e.not_(i.dest); + e.and_(i.dest, temp); + } + } else { + e.mov(i.dest, i.src2); + e.not_(i.dest); + e.and_(i.dest, uint32_t(i.src1.constant())); + } + } + } else if (i.src2.is_constant) { + // src2 constant. + if (i.dest == i.src1) { + auto temp = GetTempReg(e); + e.mov(temp, ~i.src2.constant()); + e.and_(i.dest, temp); + } else { + e.mov(i.dest, i.src1); + auto temp = GetTempReg(e); + e.mov(temp, ~i.src2.constant()); + e.and_(i.dest, temp); + } + } else { + // neither are constant + if (e.IsFeatureEnabled(kX64EmitBMI1)) { + if (i.dest.reg().getBit() == 64) { + e.andn(i.dest.reg().cvt64(), i.src2.reg().cvt64(), + i.src1.reg().cvt64()); + } else { + e.andn(i.dest.reg().cvt32(), i.src2.reg().cvt32(), + i.src1.reg().cvt32()); + } + } else { + if (i.dest == i.src2) { + e.not_(i.dest); + e.and_(i.dest, i.src1); + } else if (i.dest == i.src1) { + auto temp = GetTempReg(e); + e.mov(temp, i.src2); + e.not_(temp); + e.and_(i.dest, temp); + } else { + e.mov(i.dest, i.src2); + e.not_(i.dest); + e.and_(i.dest, i.src1); + } + } + } +} +struct AND_NOT_I8 : Sequence> { + static void Emit(X64Emitter& e, const EmitArgType& i) { + EmitAndNotXX(e, i); + } +}; +struct AND_NOT_I16 + : Sequence> { + static void Emit(X64Emitter& e, const EmitArgType& i) { + EmitAndNotXX(e, i); + } +}; +struct AND_NOT_I32 + : Sequence> { + static void Emit(X64Emitter& e, const EmitArgType& i) { + EmitAndNotXX(e, i); + } +}; +struct AND_NOT_I64 + : Sequence> { + static void Emit(X64Emitter& e, const EmitArgType& i) { + EmitAndNotXX(e, i); + } +}; +struct AND_NOT_V128 + : Sequence> { + static void Emit(X64Emitter& e, const EmitArgType& i) { + EmitCommutativeBinaryXmmOp(e, i, + [](X64Emitter& e, Xmm dest, Xmm src1, Xmm src2) { + e.vpandn(dest, src2, src1); + }); + } +}; +EMITTER_OPCODE_TABLE(OPCODE_AND_NOT, AND_NOT_I8, AND_NOT_I16, AND_NOT_I32, + AND_NOT_I64, AND_NOT_V128); + // ============================================================================ // OPCODE_OR // ============================================================================ diff --git a/src/xenia/cpu/cpu_flags.cc b/src/xenia/cpu/cpu_flags.cc index fab5ef2f0..614dabae8 100644 --- a/src/xenia/cpu/cpu_flags.cc +++ b/src/xenia/cpu/cpu_flags.cc @@ -38,6 +38,13 @@ DEFINE_bool( DEFINE_bool(validate_hir, false, "Perform validation checks on the HIR during compilation.", "CPU"); +DEFINE_uint64( + pvr, 0x710700, + "Processor version and revision number.\nBits 0 to 15 are the version " + "number.\nBits 16 to 31 are the revision number.\nNote: Some XEXs (such as " + "mfgbootlauncher.xex) may check for a value that's less than 0x710700.", + "CPU"); + // Breakpoints: DEFINE_uint64(break_on_instruction, 0, "int3 before the given guest address is executed.", "CPU"); diff --git a/src/xenia/cpu/cpu_flags.h b/src/xenia/cpu/cpu_flags.h index 65a15a87d..811e97756 100644 --- a/src/xenia/cpu/cpu_flags.h +++ b/src/xenia/cpu/cpu_flags.h @@ -26,6 +26,9 @@ DECLARE_bool(disable_global_lock); DECLARE_bool(validate_hir); +DECLARE_uint64(pvr); + +// Breakpoints: DECLARE_uint64(break_on_instruction); DECLARE_int32(break_condition_gpr); DECLARE_uint64(break_condition_value); diff --git a/src/xenia/cpu/hir/hir_builder.cc b/src/xenia/cpu/hir/hir_builder.cc index fc64b7c2e..3cc2c9aaa 100644 --- a/src/xenia/cpu/hir/hir_builder.cc +++ b/src/xenia/cpu/hir/hir_builder.cc @@ -1759,6 +1759,26 @@ Value* HIRBuilder::And(Value* value1, Value* value2) { return i->dest; } +Value* HIRBuilder::AndNot(Value* value1, Value* value2) { + ASSERT_NON_FLOAT_TYPE(value1); + ASSERT_NON_FLOAT_TYPE(value2); + ASSERT_TYPES_EQUAL(value1, value2); + + if (value1 == value2) { + return LoadZero(value1->type); + } else if (value1->IsConstantZero()) { + return value1; + } else if (value2->IsConstantZero()) { + return value1; + } + + Instr* i = AppendInstr(OPCODE_AND_NOT_info, 0, AllocValue(value1->type)); + i->set_src1(value1); + i->set_src2(value2); + i->src3.value = NULL; + return i->dest; +} + Value* HIRBuilder::Or(Value* value1, Value* value2) { ASSERT_NON_FLOAT_TYPE(value1); ASSERT_NON_FLOAT_TYPE(value2); diff --git a/src/xenia/cpu/hir/hir_builder.h b/src/xenia/cpu/hir/hir_builder.h index 81c406c12..b2809d5d8 100644 --- a/src/xenia/cpu/hir/hir_builder.h +++ b/src/xenia/cpu/hir/hir_builder.h @@ -224,6 +224,7 @@ class HIRBuilder { Value* DotProduct4(Value* value1, Value* value2); Value* And(Value* value1, Value* value2); + Value* AndNot(Value* value1, Value* value2); Value* Or(Value* value1, Value* value2); Value* Xor(Value* value1, Value* value2); Value* Not(Value* value); diff --git a/src/xenia/cpu/hir/opcodes.h b/src/xenia/cpu/hir/opcodes.h index 1649ec9dc..6f45bb8da 100644 --- a/src/xenia/cpu/hir/opcodes.h +++ b/src/xenia/cpu/hir/opcodes.h @@ -255,6 +255,7 @@ enum Opcode { OPCODE_DOT_PRODUCT_3, OPCODE_DOT_PRODUCT_4, OPCODE_AND, + OPCODE_AND_NOT, OPCODE_OR, OPCODE_XOR, OPCODE_NOT, diff --git a/src/xenia/cpu/hir/opcodes.inl b/src/xenia/cpu/hir/opcodes.inl index 9ee033aa5..584b0ac55 100644 --- a/src/xenia/cpu/hir/opcodes.inl +++ b/src/xenia/cpu/hir/opcodes.inl @@ -524,6 +524,12 @@ DEFINE_OPCODE( OPCODE_SIG_V_V_V, OPCODE_FLAG_COMMUNATIVE) +DEFINE_OPCODE( + OPCODE_AND_NOT, + "and_not", + OPCODE_SIG_V_V_V, + 0) + DEFINE_OPCODE( OPCODE_OR, "or", diff --git a/src/xenia/cpu/ppc/ppc_emit_altivec.cc b/src/xenia/cpu/ppc/ppc_emit_altivec.cc index 93f4df2b7..331713f10 100644 --- a/src/xenia/cpu/ppc/ppc_emit_altivec.cc +++ b/src/xenia/cpu/ppc/ppc_emit_altivec.cc @@ -286,7 +286,7 @@ int InstrEmit_stvlx_(PPCHIRBuilder& f, const InstrData& i, uint32_t vd, // mask = FFFF... >> eb Value* mask = f.Permute(f.LoadVectorShr(eb), f.LoadZeroVec128(), f.Not(f.LoadZeroVec128()), INT8_TYPE); - Value* v = f.Or(f.And(old_value, f.Not(mask)), f.And(new_value, mask)); + Value* v = f.Or(f.AndNot(old_value, mask), f.And(new_value, mask)); // ea &= ~0xF (handled above) f.Store(ea, f.ByteSwap(v)); return 0; @@ -328,7 +328,7 @@ int InstrEmit_stvrx_(PPCHIRBuilder& f, const InstrData& i, uint32_t vd, // mask = ~FFFF... >> eb Value* mask = f.Permute(f.LoadVectorShr(eb), f.Not(f.LoadZeroVec128()), f.LoadZeroVec128(), INT8_TYPE); - Value* v = f.Or(f.And(old_value, f.Not(mask)), f.And(new_value, mask)); + Value* v = f.Or(f.AndNot(old_value, mask), f.And(new_value, mask)); // ea &= ~0xF (handled above) f.Store(ea, f.ByteSwap(v)); f.MarkLabel(skip_label); @@ -459,7 +459,7 @@ int InstrEmit_vand128(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_vandc_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) { // VD <- (VA) & ¬(VB) - Value* v = f.And(f.LoadVR(va), f.Not(f.LoadVR(vb))); + Value* v = f.AndNot(f.LoadVR(va), f.LoadVR(vb)); f.StoreVR(vd, v); return 0; } diff --git a/src/xenia/cpu/ppc/ppc_emit_alu.cc b/src/xenia/cpu/ppc/ppc_emit_alu.cc index 78f51b106..4be752936 100644 --- a/src/xenia/cpu/ppc/ppc_emit_alu.cc +++ b/src/xenia/cpu/ppc/ppc_emit_alu.cc @@ -657,7 +657,7 @@ int InstrEmit_andx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_andcx(PPCHIRBuilder& f, const InstrData& i) { // RA <- (RS) & ¬(RB) - Value* ra = f.And(f.LoadGPR(i.X.RT), f.Not(f.LoadGPR(i.X.RB))); + Value* ra = f.AndNot(f.LoadGPR(i.X.RT), f.LoadGPR(i.X.RB)); f.StoreGPR(i.X.RA, ra); if (i.X.Rc) { f.UpdateCR(0, ra); diff --git a/src/xenia/cpu/ppc/ppc_emit_control.cc b/src/xenia/cpu/ppc/ppc_emit_control.cc index ec09ea458..416f30578 100644 --- a/src/xenia/cpu/ppc/ppc_emit_control.cc +++ b/src/xenia/cpu/ppc/ppc_emit_control.cc @@ -620,6 +620,16 @@ int InstrEmit_mfspr(PPCHIRBuilder& f, const InstrData& i) { // TBU v = f.Shr(f.LoadClock(), 32); break; + case 287: + // [ Processor Version Register (PVR) ] + // PVR is a 32 bit, read-only register within the supervisor level. + // Bits 0 to 15 are the version number. + // Bits 16 to 31 are the revision number. + // Known Values: 0x710600?, 0x710700, 0x710800 (Corona?); + // Note: Some XEXs (such as mfgbootlauncher.xex) may check for a value + // that's less than 0x710700. + v = f.LoadConstantUint64(cvars::pvr); + break; default: XEINSTRNOTIMPLEMENTED(); return 1; diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc index b2da8aff7..a39c41bd1 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc +++ b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc @@ -10,6 +10,7 @@ #include "xenia/base/console_app_main.h" #include "xenia/base/cvar.h" #include "xenia/base/filesystem.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/platform.h" @@ -36,6 +37,7 @@ namespace cpu { namespace test { using xe::cpu::ppc::PPCContext; +using namespace xe::literals; typedef std::vector> AnnotationList; @@ -177,7 +179,7 @@ class TestSuite { class TestRunner { public: - TestRunner() : memory_size_(64 * 1024 * 1024) { + TestRunner() : memory_size_(64_MiB) { memory_.reset(new Memory()); memory_->Initialize(); } @@ -420,8 +422,7 @@ bool RunTests(const std::string_view test_name) { int failed_count = 0; int passed_count = 0; - XELOGI("Haswell instruction usage {}.", - cvars::use_haswell_instructions ? "enabled" : "disabled"); + XELOGI("Instruction feature mask {}.", cvars::x64_extension_mask); auto test_path_root = cvars::test_path; std::vector test_files; diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 6aae55a6c..2fe459dc4 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -16,6 +16,7 @@ #include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/exception_handler.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/memory.h" #include "xenia/base/profiling.h" @@ -57,6 +58,8 @@ namespace cpu { using xe::cpu::ppc::PPCOpcode; using xe::kernel::XThread; +using namespace xe::literals; + class BuiltinModule : public Module { public: explicit BuiltinModule(Processor* processor) @@ -142,8 +145,8 @@ bool Processor::Setup(std::unique_ptr backend) { // Open the trace data path, if requested. functions_trace_path_ = cvars::trace_function_data_path; if (!functions_trace_path_.empty()) { - functions_trace_file_ = ChunkedMappedMemoryWriter::Open( - functions_trace_path_, 32 * 1024 * 1024, true); + functions_trace_file_ = + ChunkedMappedMemoryWriter::Open(functions_trace_path_, 32_MiB, true); } return true; diff --git a/src/xenia/cpu/testing/vector_sha_test.cc b/src/xenia/cpu/testing/vector_sha_test.cc index 5b4adabc6..187e8b4f2 100644 --- a/src/xenia/cpu/testing/vector_sha_test.cc +++ b/src/xenia/cpu/testing/vector_sha_test.cc @@ -58,6 +58,28 @@ TEST_CASE("VECTOR_SHA_I8_CONSTANT", "[instr]") { }); } +// This targets the "all_same" optimization of the Int8 specialization of +// VECTOR_SHA_V128 +TEST_CASE("VECTOR_SHA_I8_SAME_CONSTANT", "[instr]") { + TestFunction test([](HIRBuilder& b) { + StoreVR( + b, 3, + b.VectorSha(LoadVR(b, 4), b.LoadConstantVec128(vec128b(5)), INT8_TYPE)); + b.Return(); + }); + test.Run( + [](PPCContext* ctx) { + ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + }, + [](PPCContext* ctx) { + auto result = ctx->v[3]; + REQUIRE(result == vec128b(0x03, 0x03, 0x03, 0x03, 0xfc, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00)); + }); +} + TEST_CASE("VECTOR_SHA_I16", "[instr]") { TestFunction test([](HIRBuilder& b) { StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE)); diff --git a/src/xenia/cpu/testing/vector_shl_test.cc b/src/xenia/cpu/testing/vector_shl_test.cc index cdf61c4f8..bb821edca 100644 --- a/src/xenia/cpu/testing/vector_shl_test.cc +++ b/src/xenia/cpu/testing/vector_shl_test.cc @@ -58,6 +58,28 @@ TEST_CASE("VECTOR_SHL_I8_CONSTANT", "[instr]") { }); } +// This targets the "all_same" optimization of the Int8 specialization of +// VECTOR_SHL_V128 +TEST_CASE("VECTOR_SHL_I8_SAME_CONSTANT", "[instr]") { + TestFunction test([](HIRBuilder& b) { + StoreVR( + b, 3, + b.VectorShl(LoadVR(b, 4), b.LoadConstantVec128(vec128b(5)), INT8_TYPE)); + b.Return(); + }); + test.Run( + [](PPCContext* ctx) { + ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + }, + [](PPCContext* ctx) { + auto result = ctx->v[3]; + REQUIRE(result == vec128b(0xC0, 0xC0, 0xC0, 0xE0, 0x00, 0xE0, 0x20, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00)); + }); +} + TEST_CASE("VECTOR_SHL_I16", "[instr]") { TestFunction test([](HIRBuilder& b) { StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE)); diff --git a/src/xenia/cpu/testing/vector_shr_test.cc b/src/xenia/cpu/testing/vector_shr_test.cc index 8ee36ce73..000b0234e 100644 --- a/src/xenia/cpu/testing/vector_shr_test.cc +++ b/src/xenia/cpu/testing/vector_shr_test.cc @@ -58,6 +58,28 @@ TEST_CASE("VECTOR_SHR_I8_CONSTANT", "[instr]") { }); } +// This targets the "all_same" optimization of the Int8 specialization of +// VECTOR_SHR_V128 +TEST_CASE("VECTOR_SHR_I8_SAME_CONSTANT", "[instr]") { + TestFunction test([](HIRBuilder& b) { + StoreVR( + b, 3, + b.VectorShr(LoadVR(b, 4), b.LoadConstantVec128(vec128b(3)), INT8_TYPE)); + b.Return(); + }); + test.Run( + [](PPCContext* ctx) { + ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + }, + [](PPCContext* ctx) { + auto result = ctx->v[3]; + REQUIRE(result == vec128b(0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x1F, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00)); + }); +} + TEST_CASE("VECTOR_SHR_I16", "[instr]") { TestFunction test([](HIRBuilder& b) { StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE)); diff --git a/src/xenia/debug/ui/debug_window.cc b/src/xenia/debug/ui/debug_window.cc index 016952351..bcbf7e042 100644 --- a/src/xenia/debug/ui/debug_window.cc +++ b/src/xenia/debug/ui/debug_window.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -32,6 +32,8 @@ #include "xenia/kernel/xthread.h" #include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/windowed_app_context.h" DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools.", "UI"); @@ -49,14 +51,18 @@ using xe::ui::MenuItem; using xe::ui::MouseEvent; using xe::ui::UIEvent; -const std::string kBaseTitle = "Xenia Debugger"; +void DebugWindow::DebugDialog::OnDraw(ImGuiIO& io) { + debug_window_.DrawFrame(io); +} + +static const std::string kBaseTitle = "Xenia Debugger"; DebugWindow::DebugWindow(Emulator* emulator, xe::ui::WindowedAppContext& app_context) : emulator_(emulator), processor_(emulator->processor()), app_context_(app_context), - window_(xe::ui::Window::Create(app_context_, kBaseTitle)) { + window_(xe::ui::Window::Create(app_context_, kBaseTitle, 1500, 1000)) { if (cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle_) != CS_ERR_OK) { assert_always("Failed to initialize capstone"); } @@ -86,44 +92,57 @@ std::unique_ptr DebugWindow::Create( } bool DebugWindow::Initialize() { - if (!window_->Initialize()) { - XELOGE("Failed to initialize platform window"); - return false; - } - // Main menu. auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File"); { - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "&Close", - "Alt+F4", - [this]() { window_->Close(); })); + file_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "&Close", "Alt+F4", + [this]() { window_->RequestClose(); })); } main_menu->AddChild(std::move(file_menu)); - window_->set_main_menu(std::move(main_menu)); + window_->SetMainMenu(std::move(main_menu)); - window_->Resize(1500, 1000); + // Open the window once it's configured. + if (!window_->Open()) { + XELOGE("Failed to open the platform window for the debugger"); + return false; + } - // Create the graphics context used for drawing. - auto provider = emulator_->display_window()->context()->provider(); - window_->set_context(provider->CreateHostContext(window_.get())); + // Setup drawing to the window. - // Enable imgui input. - window_->set_imgui_input_enabled(true); + xe::ui::GraphicsProvider& graphics_provider = + *emulator_->graphics_system()->provider(); - window_->on_painting.AddListener([this](UIEvent* e) { DrawFrame(); }); + presenter_ = graphics_provider.CreatePresenter(); + if (!presenter_) { + XELOGE("Failed to initialize the presenter for the debugger"); + return false; + } + immediate_drawer_ = graphics_provider.CreateImmediateDrawer(); + if (!immediate_drawer_) { + XELOGE("Failed to initialize the immediate drawer for the debugger"); + return false; + } + immediate_drawer_->SetPresenter(presenter_.get()); + + imgui_drawer_ = std::make_unique(window_.get(), 0); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + immediate_drawer_.get()); + debug_dialog_ = + std::unique_ptr(new DebugDialog(imgui_drawer_.get(), *this)); + + // Update the cache before the first frame. UpdateCache(); - window_->Invalidate(); + + // Begin drawing. + window_->SetPresenter(presenter_.get()); return true; } -void DebugWindow::DrawFrame() { - xe::ui::GraphicsContextLock lock(window_->context()); - - auto& io = window_->imgui_drawer()->GetIO(); - +void DebugWindow::DrawFrame(ImGuiIO& io) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(-1, 0)); ImGui::Begin("main_window", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | @@ -242,9 +261,6 @@ void DebugWindow::DrawFrame() { ImGui::ShowDemoWindow(); ImGui::ShowMetricsWindow(); } - - // Continuous paint. - window_->Invalidate(); } void DebugWindow::DrawToolbar() { @@ -1443,7 +1459,7 @@ void DebugWindow::UpdateCache() { title += " (stepping)"; break; } - window_->set_title(title); + window_->SetTitle(title); }); cache_.is_running = @@ -1573,7 +1589,7 @@ void DebugWindow::OnBreakpointHit(Breakpoint* breakpoint, } void DebugWindow::Focus() const { - app_context_.CallInUIThread([this]() { window_->set_focus(true); }); + app_context_.CallInUIThread([this]() { window_->Focus(); }); } } // namespace ui diff --git a/src/xenia/debug/ui/debug_window.h b/src/xenia/debug/ui/debug_window.h index 7c9cfae4f..be7294940 100644 --- a/src/xenia/debug/ui/debug_window.h +++ b/src/xenia/debug/ui/debug_window.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,7 +18,11 @@ #include "xenia/cpu/debug_listener.h" #include "xenia/cpu/processor.h" #include "xenia/emulator.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" #include "xenia/ui/menu_item.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" @@ -48,11 +52,24 @@ class DebugWindow : public cpu::DebugListener { cpu::ThreadDebugInfo* thread_info) override; private: + class DebugDialog final : public xe::ui::ImGuiDialog { + public: + explicit DebugDialog(xe::ui::ImGuiDrawer* imgui_drawer, + DebugWindow& debug_window) + : xe::ui::ImGuiDialog(imgui_drawer), debug_window_(debug_window) {} + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + DebugWindow& debug_window_; + }; + explicit DebugWindow(Emulator* emulator, xe::ui::WindowedAppContext& app_context); bool Initialize(); - void DrawFrame(); + void DrawFrame(ImGuiIO& io); void DrawToolbar(); void DrawFunctionsPane(); void DrawSourcePane(); @@ -93,7 +110,10 @@ class DebugWindow : public cpu::DebugListener { cpu::Processor* processor_ = nullptr; xe::ui::WindowedAppContext& app_context_; std::unique_ptr window_; - uint64_t last_draw_tick_count_ = 0; + std::unique_ptr presenter_; + std::unique_ptr immediate_drawer_; + std::unique_ptr imgui_drawer_; + std::unique_ptr debug_dialog_; uintptr_t capstone_handle_ = 0; diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index 7bb4109e4..0fbf74d18 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -9,6 +9,7 @@ #include "xenia/emulator.h" +#include #include #include "config.h" @@ -20,9 +21,9 @@ #include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/exception_handler.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/mapped_memory.h" -#include "xenia/base/profiling.h" #include "xenia/base/string.h" #include "xenia/cpu/backend/code_cache.h" #include "xenia/cpu/backend/x64/x64_backend.h" @@ -40,6 +41,7 @@ #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" #include "xenia/memory.h" #include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/vfs/devices/disc_image_device.h" @@ -60,6 +62,17 @@ DEFINE_string( namespace xe { +using namespace xe::literals; + +Emulator::GameConfigLoadCallback::GameConfigLoadCallback(Emulator& emulator) + : emulator_(emulator) { + emulator_.AddGameConfigLoadCallback(this); +} + +Emulator::GameConfigLoadCallback::~GameConfigLoadCallback() { + emulator_.RemoveGameConfigLoadCallback(this); +} + Emulator::Emulator(const std::filesystem::path& command_line, const std::filesystem::path& storage_root, const std::filesystem::path& content_root, @@ -113,7 +126,7 @@ Emulator::~Emulator() { } X_STATUS Emulator::Setup( - ui::Window* display_window, + ui::Window* display_window, ui::ImGuiDrawer* imgui_drawer, std::function(cpu::Processor*)> audio_system_factory, std::function()> @@ -123,6 +136,7 @@ X_STATUS Emulator::Setup( X_STATUS result = X_STATUS_UNSUCCESSFUL; display_window_ = display_window; + imgui_drawer_ = imgui_drawer; // Initialize clock. // 360 uses a 50MHz clock. @@ -209,8 +223,10 @@ X_STATUS Emulator::Setup( kernel_state_ = std::make_unique(this); // Setup the core components. - result = graphics_system_->Setup(processor_.get(), kernel_state_.get(), - display_window_); + result = graphics_system_->Setup( + processor_.get(), kernel_state_.get(), + display_window_ ? &display_window_->app_context() : nullptr, + display_window_ != nullptr); if (result) { return result; } @@ -233,14 +249,6 @@ X_STATUS Emulator::Setup( // Initialize emulator fallback exception handling last. ExceptionHandler::Install(Emulator::ExceptionCallbackThunk, this); - if (display_window_) { - // Finish initializing the display. - display_window_->app_context().CallInUIThreadSynchronous([this]() { - xe::ui::GraphicsContextLock context_lock(display_window_->context()); - Profiler::set_window(display_window_); - }); - } - return result; } @@ -414,9 +422,8 @@ void Emulator::Resume() { bool Emulator::SaveToFile(const std::filesystem::path& path) { Pause(); - filesystem::CreateFile(path); - auto map = MappedMemory::Open(path, MappedMemory::Mode::kReadWrite, 0, - 1024ull * 1024ull * 1024ull * 2ull); + filesystem::CreateEmptyFile(path); + auto map = MappedMemory::Open(path, MappedMemory::Mode::kReadWrite, 0, 2_GiB); if (!map) { return false; } @@ -585,14 +592,16 @@ bool Emulator::ExceptionCallback(Exception* ex) { } // Display a dialog telling the user the guest has crashed. - display_window()->app_context().CallInUIThreadSynchronous([this]() { - xe::ui::ImGuiDialog::ShowMessageBox( - display_window(), "Uh-oh!", - "The guest has crashed.\n\n" - "" - "Xenia has now paused itself.\n" - "A crash dump has been written into the log."); - }); + if (display_window_ && imgui_drawer_) { + display_window_->app_context().CallInUIThreadSynchronous([this]() { + xe::ui::ImGuiDialog::ShowMessageBox( + imgui_drawer_, "Uh-oh!", + "The guest has crashed.\n\n" + "" + "Xenia has now paused itself.\n" + "A crash dump has been written into the log."); + }); + } // Now suspend ourself (we should be a guest thread). current_thread->Suspend(nullptr); @@ -619,6 +628,41 @@ void Emulator::WaitUntilExit() { on_exit(); } +void Emulator::AddGameConfigLoadCallback(GameConfigLoadCallback* callback) { + assert_not_null(callback); + // Game config load callbacks handling is entirely in the UI thread. + assert_true(!display_window_ || + display_window_->app_context().IsInUIThread()); + // Check if already added. + if (std::find(game_config_load_callbacks_.cbegin(), + game_config_load_callbacks_.cend(), + callback) != game_config_load_callbacks_.cend()) { + return; + } + game_config_load_callbacks_.push_back(callback); +} + +void Emulator::RemoveGameConfigLoadCallback(GameConfigLoadCallback* callback) { + assert_not_null(callback); + // Game config load callbacks handling is entirely in the UI thread. + assert_true(!display_window_ || + display_window_->app_context().IsInUIThread()); + auto it = std::find(game_config_load_callbacks_.cbegin(), + game_config_load_callbacks_.cend(), callback); + if (it == game_config_load_callbacks_.cend()) { + return; + } + if (game_config_load_callback_loop_next_index_ != SIZE_MAX) { + // Actualize the next callback index after the erasure from the vector. + size_t existing_index = + size_t(std::distance(game_config_load_callbacks_.cbegin(), it)); + if (game_config_load_callback_loop_next_index_ > existing_index) { + --game_config_load_callback_loop_next_index_; + } + } + game_config_load_callbacks_.erase(it); +} + std::string Emulator::FindLaunchModule() { std::string path("game:\\"); @@ -675,6 +719,10 @@ static std::string format_version(xex2_version version) { X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, const std::string_view module_path) { + // Making changes to the UI (setting the icon) and executing game config load + // callbacks which expect to be called from the UI thread. + assert_true(display_window_->app_context().IsInUIThread()); + // Setup NullDevices for raw HDD partition accesses // Cache/STFC code baked into games tries reading/writing to these // By using a NullDevice that just returns success to all IO requests it @@ -727,7 +775,19 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, // Try and load the resource database (xex only). if (module->title_id()) { auto title_id = fmt::format("{:08X}", module->title_id()); + + // Load the per-game configuration file and make sure updates are handled by + // the callbacks. config::LoadGameConfig(title_id); + assert_true(game_config_load_callback_loop_next_index_ == SIZE_MAX); + game_config_load_callback_loop_next_index_ = 0; + while (game_config_load_callback_loop_next_index_ < + game_config_load_callbacks_.size()) { + game_config_load_callbacks_[game_config_load_callback_loop_next_index_++] + ->PostGameConfigLoad(); + } + game_config_load_callback_loop_next_index_ = SIZE_MAX; + uint32_t resource_data = 0; uint32_t resource_size = 0; if (XSUCCEEDED(module->GetSection(title_id.c_str(), &resource_data, diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index cd86e1f81..96d81d00a 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -10,9 +10,12 @@ #ifndef XENIA_EMULATOR_H_ #define XENIA_EMULATOR_H_ +#include +#include #include #include #include +#include #include "xenia/base/delegate.h" #include "xenia/base/exception_handler.h" @@ -38,6 +41,7 @@ class InputDriver; class InputSystem; } // namespace hid namespace ui { +class ImGuiDrawer; class Window; } // namespace ui } // namespace xe @@ -50,6 +54,37 @@ constexpr fourcc_t kEmulatorSaveSignature = make_fourcc("XSAV"); // This is responsible for initializing and managing all the various subsystems. class Emulator { public: + // This is the class for the top-level callbacks. They may be called in an + // undefined order, so among them there must be no dependencies on each other, + // especially hierarchical ones. If hierarchical handling is needed, for + // instance, if a specific implementation of a subsystem needs to handle + // changes, but the entire implementation must be reloaded, the implementation + // in this example _must not_ register / unregister its own callback - rather, + // the proper ordering and hierarchy should be constructed in a single + // callback (in this example, for the whole subsystem). + // + // All callbacks must be created and destroyed in the UI thread only (or the + // thread that takes its place in the architecture of the specific app if + // there's no UI), as they are invoked in the UI thread. + class GameConfigLoadCallback { + public: + GameConfigLoadCallback(Emulator& emulator); + GameConfigLoadCallback(const GameConfigLoadCallback& callback) = delete; + GameConfigLoadCallback& operator=(const GameConfigLoadCallback& callback) = + delete; + virtual ~GameConfigLoadCallback(); + + // The callback is invoked in the UI thread (or the thread that takes its + // place in the architecture of the specific app if there's no UI). + virtual void PostGameConfigLoad() = 0; + + protected: + Emulator& emulator() const { return emulator_; } + + private: + Emulator& emulator_; + }; + explicit Emulator(const std::filesystem::path& command_line, const std::filesystem::path& storage_root, const std::filesystem::path& content_root, @@ -82,9 +117,13 @@ class Emulator { // Are we currently running a title? bool is_title_open() const { return title_id_.has_value(); } - // Window used for displaying graphical output. + // Window used for displaying graphical output. Can be null. ui::Window* display_window() const { return display_window_; } + // ImGui drawer for various kinds of dialogs requested by the guest. Can be + // null. + ui::ImGuiDrawer* imgui_drawer() const { return imgui_drawer_; } + // Guest memory system modelling the RAM (both virtual and physical) of the // system. Memory* memory() const { return memory_.get(); } @@ -121,7 +160,7 @@ class Emulator { // Once this function returns a game can be launched using one of the Launch // functions. X_STATUS Setup( - ui::Window* display_window, + ui::Window* display_window, ui::ImGuiDrawer* imgui_drawer, std::function(cpu::Processor*)> audio_system_factory, std::function()> @@ -170,6 +209,9 @@ class Emulator { static bool ExceptionCallbackThunk(Exception* ex, void* data); bool ExceptionCallback(Exception* ex); + void AddGameConfigLoadCallback(GameConfigLoadCallback* callback); + void RemoveGameConfigLoadCallback(GameConfigLoadCallback* callback); + std::string FindLaunchModule(); X_STATUS CompleteLaunch(const std::filesystem::path& path, @@ -183,7 +225,8 @@ class Emulator { std::string title_name_; std::string title_version_; - ui::Window* display_window_; + ui::Window* display_window_ = nullptr; + ui::ImGuiDrawer* imgui_drawer_ = nullptr; std::unique_ptr memory_; @@ -196,6 +239,16 @@ class Emulator { std::unique_ptr file_system_; std::unique_ptr kernel_state_; + + // Accessible only from the thread that invokes those callbacks (the UI thread + // if the UI is available). + std::vector game_config_load_callbacks_; + // Using an index, not an iterator, because after the erasure, the adjustment + // must be done for the vector element indices that would be in the iterator + // range that would be invalidated. + // SIZE_MAX if not currently in the game config load callback loop. + size_t game_config_load_callback_loop_next_index_ = SIZE_MAX; + kernel::object_ref main_thread_; std::optional title_id_; // Currently running title ID diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index 2e1a43c36..7a4ac4e23 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -45,15 +45,12 @@ CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system, CommandProcessor::~CommandProcessor() = default; -bool CommandProcessor::Initialize( - std::unique_ptr context) { - context_ = std::move(context); - +bool CommandProcessor::Initialize() { // Initialize the gamma ramps to their default (linear) values - taken from // what games set when starting. for (uint32_t i = 0; i < 256; ++i) { uint32_t value = i * 1023 / 255; - gamma_ramp_.normal[i].value = value | (value << 10) | (value << 20); + gamma_ramp_.table[i].value = value | (value << 10) | (value << 20); } for (uint32_t i = 0; i < 128; ++i) { uint32_t value = (i * 65535 / 127) & ~63; @@ -64,7 +61,7 @@ bool CommandProcessor::Initialize( gamma_ramp_.pwl[i].values[j].value = value; } } - dirty_gamma_ramp_normal_ = true; + dirty_gamma_ramp_table_ = true; dirty_gamma_ramp_pwl_ = true; worker_running_ = true; @@ -140,8 +137,18 @@ void CommandProcessor::CallInThread(std::function fn) { void CommandProcessor::ClearCaches() {} +void CommandProcessor::SetDesiredSwapPostEffect( + SwapPostEffect swap_post_effect) { + if (swap_post_effect_desired_ == swap_post_effect) { + return; + } + swap_post_effect_desired_ = swap_post_effect; + CallInThread([this, swap_post_effect]() { + swap_post_effect_actual_ = swap_post_effect; + }); +} + void CommandProcessor::WorkerThreadMain() { - context_->MakeCurrent(); if (!SetupContext()) { xe::FatalError("Unable to setup command processor internal state"); return; @@ -212,9 +219,6 @@ void CommandProcessor::Pause() { threading::Thread::GetCurrentThread()->Suspend(); }); - // HACK - Prevents a hang in IssueSwap() - swap_state_.pending = false; - fence.Wait(); } @@ -255,7 +259,7 @@ bool CommandProcessor::Restore(ByteStream* stream) { bool CommandProcessor::SetupContext() { return true; } -void CommandProcessor::ShutdownContext() { context_.reset(); } +void CommandProcessor::ShutdownContext() {} void CommandProcessor::InitializeRingBuffer(uint32_t ptr, uint32_t size_log2) { read_ptr_index_ = 0; @@ -326,14 +330,17 @@ void CommandProcessor::UpdateGammaRampValue(GammaRampType type, if (mask_lo) { switch (type) { - case GammaRampType::kNormal: + case GammaRampType::kTable: assert_true(regs->values[XE_GPU_REG_DC_LUT_RW_MODE].u32 == 0); - gamma_ramp_.normal[index].value = value; - dirty_gamma_ramp_normal_ = true; + gamma_ramp_.table[index].value = value; + dirty_gamma_ramp_table_ = true; break; case GammaRampType::kPWL: assert_true(regs->values[XE_GPU_REG_DC_LUT_RW_MODE].u32 == 1); - gamma_ramp_.pwl[index].values[gamma_ramp_rw_subindex_].value = value; + // The lower 6 bits are hardwired to 0. + // https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf + gamma_ramp_.pwl[index].values[gamma_ramp_rw_subindex_].value = + value & ~(uint32_t(63) | (uint32_t(63) << 16)); gamma_ramp_rw_subindex_ = (gamma_ramp_rw_subindex_ + 1) % 3; dirty_gamma_ramp_pwl_ = true; break; @@ -385,51 +392,6 @@ void CommandProcessor::PrepareForWait() { trace_writer_.Flush(); } void CommandProcessor::ReturnFromWait() {} -void CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, - uint32_t frontbuffer_width, - uint32_t frontbuffer_height) { - SCOPE_profile_cpu_f("gpu"); - if (!swap_request_handler_) { - return; - } - - // If there was a swap pending we drop it on the floor. - // This prevents the display from pulling the backbuffer out from under us. - // If we skip a lot then we may need to buffer more, but as the display - // thread should be fairly idle that shouldn't happen. - if (!cvars::vsync) { - std::lock_guard lock(swap_state_.mutex); - if (swap_state_.pending) { - swap_state_.pending = false; - // TODO(benvanik): frame skip counter. - XELOGW("Skipped frame!"); - } - } else { - // Spin until no more pending swap. - while (worker_running_) { - { - std::lock_guard lock(swap_state_.mutex); - if (!swap_state_.pending) { - break; - } - } - xe::threading::MaybeYield(); - } - } - - PerformSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height); - - { - // Set pending so that the display will swap the next time it can. - std::lock_guard lock(swap_state_.mutex); - swap_state_.pending = true; - } - - // Notify the display a swap is pending so that our changes are picked up. - // It does the actual front/back buffer swap. - swap_request_handler_(); -} - uint32_t CommandProcessor::ExecutePrimaryBuffer(uint32_t read_index, uint32_t write_index) { SCOPE_profile_cpu_f("gpu"); @@ -440,7 +402,7 @@ uint32_t CommandProcessor::ExecutePrimaryBuffer(uint32_t read_index, uint32_t title_id = kernel_state_->GetExecutableModule() ? kernel_state_->GetExecutableModule()->title_id() : 0; - auto file_name = fmt::format("{:8X}_stream.xtr", title_id); + auto file_name = fmt::format("{:08X}_stream.xtr", title_id); auto path = trace_stream_path_ / file_name; trace_writer_.Open(path, title_id); InitializeTrace(); @@ -767,7 +729,7 @@ bool CommandProcessor::ExecutePacketType3(RingBuffer* reader, uint32_t packet) { } else if (trace_state_ == TraceState::kSingleFrame) { // New trace request - we only start tracing at the beginning of a frame. uint32_t title_id = kernel_state_->GetExecutableModule()->title_id(); - auto file_name = fmt::format("{:8X}_{}.xtr", title_id, counter_ - 1); + auto file_name = fmt::format("{:08X}_{}.xtr", title_id, counter_ - 1); auto path = trace_frame_path_ / file_name; trace_writer_.Open(path, title_id); InitializeTrace(); @@ -837,7 +799,7 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingBuffer* reader, uint32_t frontbuffer_height = reader->ReadAndSwap(); reader->AdvanceRead((count - 4) * sizeof(uint32_t)); - if (swap_mode_ == SwapMode::kNormal) { + if (!ignore_swap_) { IssueSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height); } diff --git a/src/xenia/gpu/command_processor.h b/src/xenia/gpu/command_processor.h index d2ee29d8f..caa49e300 100644 --- a/src/xenia/gpu/command_processor.h +++ b/src/xenia/gpu/command_processor.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -26,7 +26,7 @@ #include "xenia/gpu/xenos.h" #include "xenia/kernel/xthread.h" #include "xenia/memory.h" -#include "xenia/ui/graphics_context.h" +#include "xenia/ui/presenter.h" namespace xe { @@ -60,12 +60,20 @@ enum class SwapMode { enum class GammaRampType { kUnknown = 0, - kNormal, + kTable, kPWL, }; struct GammaRamp { - struct NormalEntry { + // A lot of gamma ramp (DC_LUT) documentation: + // https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf + // The ramps entries are BGR, not RGB. + // For the 256-entry table (used by Direct3D 9 for a 8bpc front buffer), + // 535107D4 has in-game settings allowing separate configuration. + // The component order of the PWL table is untested, however, it's likely BGR + // too, since DC_LUTA/B registers have values for blue first, and for red + // last. + struct TableEntry { union { uint32_t value; struct { @@ -81,6 +89,15 @@ struct GammaRamp { union { uint32_t value; struct { + // The lower 6 bits are always zero (these are 10-bit in the upper bits + // thus, not fully 16-bit). + // See DC_LUTA/B_CONTROL for information about the way they should be + // interpreted (`output = base + (multiplier * delta) / 2^increment`, + // where the increment is the value specified in DC_LUTA/B_CONTROL for + // the specific color channel, the base is 7 bits of the front buffer + // value above `increment` bits, the multiplier is the lower `increment` + // bits of it; the increment is nonzero, otherwise the 256-entry table + // should be used instead). uint16_t base; uint16_t delta; }; @@ -91,19 +108,25 @@ struct GammaRamp { union { PWLValue values[3]; struct { - PWLValue r; - PWLValue g; PWLValue b; + PWLValue g; + PWLValue r; }; }; }; - NormalEntry normal[256]; + TableEntry table[256]; PWLEntry pwl[128]; }; class CommandProcessor { public: + enum class SwapPostEffect { + kNone, + kFxaa, + kFxaaExtreme, + }; + CommandProcessor(GraphicsSystem* graphics_system, kernel::KernelState* kernel_state); virtual ~CommandProcessor(); @@ -114,21 +137,26 @@ class CommandProcessor { Shader* active_vertex_shader() const { return active_vertex_shader_; } Shader* active_pixel_shader() const { return active_pixel_shader_; } - virtual bool Initialize(std::unique_ptr context); + virtual bool Initialize(); virtual void Shutdown(); void CallInThread(std::function fn); virtual void ClearCaches(); - SwapState& swap_state() { return swap_state_; } - void set_swap_mode(SwapMode swap_mode) { swap_mode_ = swap_mode; } - void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height); - - void set_swap_request_handler(std::function fn) { - swap_request_handler_ = fn; + void SetIgnoreSwap(bool ignore_swap) { ignore_swap_ = ignore_swap; } + // "Desired" is for the external thread managing the post-processing effect. + SwapPostEffect GetDesiredSwapPostEffect() const { + return swap_post_effect_desired_; } + void SetDesiredSwapPostEffect(SwapPostEffect swap_post_effect); + // Implementations must not make assumptions that the front buffer will + // necessarily be a resolve destination - it may be a texture generated by any + // means like written to by the CPU or loaded from a file (the disclaimer + // screen right in the beginning of 4D530AA4 is not a resolved render target, + // for instance). + virtual void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, + uint32_t frontbuffer_height) = 0; // May be called not only from the command processor thread when the command // processor is paused, and the termination of this function may be explicitly @@ -179,9 +207,6 @@ class CommandProcessor { virtual void PrepareForWait(); virtual void ReturnFromWait(); - virtual void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height) = 0; - uint32_t ExecutePrimaryBuffer(uint32_t start_index, uint32_t end_index); virtual void OnPrimaryBufferEnd() {} void ExecuteIndirectBuffer(uint32_t ptr, uint32_t length); @@ -254,6 +279,14 @@ class CommandProcessor { bool major_mode_explicit) = 0; virtual bool IssueCopy() = 0; + // "Actual" is for the command processor thread, to be read by the + // implementations. + SwapPostEffect GetActualSwapPostEffect() const { + return swap_post_effect_actual_; + } + + // TODO(Triang3l): Write the gamma ramp (including the display controller + // write pointers) in the common code. virtual void InitializeTrace() = 0; Memory* memory_ = nullptr; @@ -274,10 +307,8 @@ class CommandProcessor { std::atomic worker_running_; kernel::object_ref worker_thread_; - std::unique_ptr context_; - SwapMode swap_mode_ = SwapMode::kNormal; - SwapState swap_state_; - std::function swap_request_handler_; + bool ignore_swap_ = false; + std::queue> pending_fns_; // MicroEngine binary from PM4_ME_INIT @@ -305,8 +336,13 @@ class CommandProcessor { GammaRamp gamma_ramp_ = {}; int gamma_ramp_rw_subindex_ = 0; - bool dirty_gamma_ramp_normal_ = true; + bool dirty_gamma_ramp_table_ = true; bool dirty_gamma_ramp_pwl_ = true; + + // By default (such as for tools), post-processing is disabled. + // "Desired" is for the external thread managing the post-processing effect. + SwapPostEffect swap_post_effect_desired_ = SwapPostEffect::kNone; + SwapPostEffect swap_post_effect_actual_ = SwapPostEffect::kNone; }; } // namespace gpu diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 5d9be3660..ccab20972 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -23,6 +23,7 @@ #include "xenia/gpu/draw_util.h" #include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/xenos.h" +#include "xenia/ui/d3d12/d3d12_presenter.h" #include "xenia/ui/d3d12/d3d12_util.h" DEFINE_bool(d3d12_bindless, true, @@ -51,6 +52,16 @@ namespace xe { namespace gpu { namespace d3d12 { +// Generated with `xb buildshaders`. +namespace shaders { +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h" +} // namespace shaders + D3D12CommandProcessor::D3D12CommandProcessor( D3D12GraphicsSystem* graphics_system, kernel::KernelState* kernel_state) : CommandProcessor(graphics_system, kernel_state), @@ -71,7 +82,7 @@ void D3D12CommandProcessor::InitializeShaderStorage( void D3D12CommandProcessor::RequestFrameTrace( const std::filesystem::path& root_path) { // Capture with PIX if attached. - if (GetD3D12Context().GetD3D12Provider().GetGraphicsAnalysis() != nullptr) { + if (GetD3D12Provider().GetGraphicsAnalysis() != nullptr) { pix_capture_requested_.store(true, std::memory_order_relaxed); return; } @@ -86,7 +97,9 @@ void D3D12CommandProcessor::TracePlaybackWroteMemory(uint32_t base_ptr, void D3D12CommandProcessor::RestoreEdramSnapshot(const void* snapshot) { // Starting a new frame because descriptors may be needed. - BeginSubmission(true); + if (!BeginSubmission(true)) { + return; + } render_target_cache_->RestoreEdramSnapshot(snapshot); } @@ -364,8 +377,8 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature( ++desc.NumParameters; } - ID3D12RootSignature* root_signature = ui::d3d12::util::CreateRootSignature( - GetD3D12Context().GetD3D12Provider(), desc); + ID3D12RootSignature* root_signature = + ui::d3d12::util::CreateRootSignature(GetD3D12Provider(), desc); if (root_signature == nullptr) { XELOGE( "Failed to create a root signature with {} pixel textures, {} pixel " @@ -430,7 +443,7 @@ uint64_t D3D12CommandProcessor::RequestViewBindfulDescriptors( deferred_command_list_.SetDescriptorHeaps(view_bindful_heap_current_, sampler_bindful_heap_current_); } - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); cpu_handle_out = provider.OffsetViewDescriptor( view_bindful_heap_pool_->GetLastRequestHeapCPUStart(), descriptor_index); gpu_handle_out = provider.OffsetViewDescriptor( @@ -464,7 +477,7 @@ bool D3D12CommandProcessor::RequestOneUseSingleViewDescriptors( return true; } assert_not_null(handles_out); - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); if (bindless_resources_used_) { // Request separate bindless descriptors that will be freed when this // submission is completed by the GPU. @@ -511,7 +524,7 @@ ui::d3d12::util::DescriptorCpuGpuHandlePair D3D12CommandProcessor::GetSystemBindlessViewHandlePair( SystemBindlessView view) const { assert_true(bindless_resources_used_); - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); return std::make_pair(provider.OffsetViewDescriptor( view_bindless_heap_cpu_start_, uint32_t(view)), provider.OffsetViewDescriptor( @@ -623,7 +636,7 @@ uint64_t D3D12CommandProcessor::RequestSamplerBindfulDescriptors( deferred_command_list_.SetDescriptorHeaps(view_bindful_heap_current_, sampler_bindful_heap_current_); } - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); cpu_handle_out = provider.OffsetSamplerDescriptor( sampler_bindful_heap_pool_->GetLastRequestHeapCPUStart(), descriptor_index); @@ -650,8 +663,8 @@ ID3D12Resource* D3D12CommandProcessor::RequestScratchGPUBuffer( size = xe::align(size, kScratchBufferSizeIncrement); - auto& provider = GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); D3D12_RESOURCE_DESC buffer_desc; ui::d3d12::util::FillBufferResourceDesc( buffer_desc, size, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); @@ -664,8 +677,7 @@ ID3D12Resource* D3D12CommandProcessor::RequestScratchGPUBuffer( return nullptr; } if (scratch_buffer_ != nullptr) { - buffers_for_deletion_.push_back( - std::make_pair(scratch_buffer_, submission_current_)); + resources_for_deletion_.emplace_back(submission_current_, scratch_buffer_); } scratch_buffer_ = buffer; scratch_buffer_size_ = size; @@ -789,76 +801,15 @@ std::string D3D12CommandProcessor::GetWindowTitleText() const { return title.str(); } -std::unique_ptr D3D12CommandProcessor::Capture() { - ID3D12Resource* readback_buffer = - RequestReadbackBuffer(uint32_t(swap_texture_copy_size_)); - if (!readback_buffer) { - return nullptr; - } - BeginSubmission(false); - PushTransitionBarrier(swap_texture_, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - D3D12_RESOURCE_STATE_COPY_SOURCE); - SubmitBarriers(); - D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; - location_source.pResource = swap_texture_; - location_source.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - location_source.SubresourceIndex = 0; - location_dest.pResource = readback_buffer; - location_dest.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - location_dest.PlacedFootprint = swap_texture_copy_footprint_; - deferred_command_list_.CopyTexture(location_dest, location_source); - PushTransitionBarrier(swap_texture_, D3D12_RESOURCE_STATE_COPY_SOURCE, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - if (!AwaitAllQueueOperationsCompletion()) { - return nullptr; - } - D3D12_RANGE readback_range; - readback_range.Begin = swap_texture_copy_footprint_.Offset; - readback_range.End = swap_texture_copy_size_; - void* readback_mapping; - if (FAILED(readback_buffer->Map(0, &readback_range, &readback_mapping))) { - return nullptr; - } - std::unique_ptr raw_image(new xe::ui::RawImage()); - auto swap_texture_size = GetSwapTextureSize(); - raw_image->width = swap_texture_size.first; - raw_image->height = swap_texture_size.second; - raw_image->stride = swap_texture_size.first * 4; - raw_image->data.resize(raw_image->stride * swap_texture_size.second); - const uint8_t* readback_source_data = - reinterpret_cast(readback_mapping) + - swap_texture_copy_footprint_.Offset; - static_assert( - ui::d3d12::D3D12Context::kSwapChainFormat == DXGI_FORMAT_B8G8R8A8_UNORM, - "D3D12CommandProcessor::Capture assumes swap_texture_ to be in " - "DXGI_FORMAT_B8G8R8A8_UNORM because it swaps red and blue"); - for (uint32_t i = 0; i < swap_texture_size.second; ++i) { - uint8_t* pixel_dest = raw_image->data.data() + i * raw_image->stride; - const uint8_t* pixel_source = - readback_source_data + - i * swap_texture_copy_footprint_.Footprint.RowPitch; - for (uint32_t j = 0; j < swap_texture_size.first; ++j) { - pixel_dest[0] = pixel_source[2]; - pixel_dest[1] = pixel_source[1]; - pixel_dest[2] = pixel_source[0]; - pixel_dest[3] = pixel_source[3]; - pixel_dest += 4; - pixel_source += 4; - } - } - return raw_image; -} - bool D3D12CommandProcessor::SetupContext() { if (!CommandProcessor::SetupContext()) { XELOGE("Failed to initialize base command processor context"); return false; } - auto& provider = GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); - auto direct_queue = provider.GetDirectQueue(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); + ID3D12CommandQueue* direct_queue = provider.GetDirectQueue(); fence_completion_event_ = CreateEvent(nullptr, FALSE, FALSE, nullptr); if (fence_completion_event_ == nullptr) { @@ -1222,120 +1173,255 @@ bool D3D12CommandProcessor::SetupContext() { D3D12_HEAP_FLAGS heap_flag_create_not_zeroed = provider.GetHeapFlagCreateNotZeroed(); - // Create gamma ramp resources. The PWL gamma ramp is 16-bit, but 6 bits are - // hardwired to zero, so DXGI_FORMAT_R10G10B10A2_UNORM can be used for it too. - // https://www.x.org/docs/AMD/old/42590_m76_rrg_1.01o.pdf - dirty_gamma_ramp_normal_ = true; + // Create gamma ramp resources. + dirty_gamma_ramp_table_ = true; dirty_gamma_ramp_pwl_ = true; - D3D12_RESOURCE_DESC gamma_ramp_desc; - gamma_ramp_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D; - gamma_ramp_desc.Alignment = 0; - gamma_ramp_desc.Width = 256; - gamma_ramp_desc.Height = 1; - gamma_ramp_desc.DepthOrArraySize = 1; - // Normal gamma is 256x1, PWL gamma is 128x1. - gamma_ramp_desc.MipLevels = 2; - gamma_ramp_desc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; - gamma_ramp_desc.SampleDesc.Count = 1; - gamma_ramp_desc.SampleDesc.Quality = 0; - gamma_ramp_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - gamma_ramp_desc.Flags = D3D12_RESOURCE_FLAG_NONE; + D3D12_RESOURCE_DESC gamma_ramp_buffer_desc; + ui::d3d12::util::FillBufferResourceDesc( + gamma_ramp_buffer_desc, (256 + 128 * 3) * 4, D3D12_RESOURCE_FLAG_NONE); // The first action will be uploading. - gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_COPY_DEST; + gamma_ramp_buffer_state_ = D3D12_RESOURCE_STATE_COPY_DEST; if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, - &gamma_ramp_desc, gamma_ramp_texture_state_, nullptr, - IID_PPV_ARGS(&gamma_ramp_texture_)))) { - XELOGE("Failed to create the gamma ramp texture"); + &gamma_ramp_buffer_desc, gamma_ramp_buffer_state_, nullptr, + IID_PPV_ARGS(&gamma_ramp_buffer_)))) { + XELOGE("Failed to create the gamma ramp buffer"); return false; } - // Get the layout for the upload buffer. - gamma_ramp_desc.DepthOrArraySize = kQueueFrames; - UINT64 gamma_ramp_upload_size; - device->GetCopyableFootprints(&gamma_ramp_desc, 0, kQueueFrames * 2, 0, - gamma_ramp_footprints_, nullptr, nullptr, - &gamma_ramp_upload_size); - // Create the upload buffer for the gamma ramp. - ui::d3d12::util::FillBufferResourceDesc( - gamma_ramp_desc, gamma_ramp_upload_size, D3D12_RESOURCE_FLAG_NONE); + // The upload buffer is frame-buffered. + gamma_ramp_buffer_desc.Width *= kQueueFrames; if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesUpload, heap_flag_create_not_zeroed, - &gamma_ramp_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, - IID_PPV_ARGS(&gamma_ramp_upload_)))) { + &gamma_ramp_buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + IID_PPV_ARGS(&gamma_ramp_upload_buffer_)))) { XELOGE("Failed to create the gamma ramp upload buffer"); return false; } - if (FAILED(gamma_ramp_upload_->Map( - 0, nullptr, reinterpret_cast(&gamma_ramp_upload_mapping_)))) { + if (FAILED(gamma_ramp_upload_buffer_->Map( + 0, nullptr, + reinterpret_cast(&gamma_ramp_upload_buffer_mapping_)))) { XELOGE("Failed to map the gamma ramp upload buffer"); - gamma_ramp_upload_mapping_ = nullptr; + gamma_ramp_upload_buffer_mapping_ = nullptr; return false; } - D3D12_RESOURCE_DESC swap_texture_desc; - swap_texture_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - swap_texture_desc.Alignment = 0; - auto swap_texture_size = GetSwapTextureSize(); - swap_texture_desc.Width = swap_texture_size.first; - swap_texture_desc.Height = swap_texture_size.second; - swap_texture_desc.DepthOrArraySize = 1; - swap_texture_desc.MipLevels = 1; - swap_texture_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat; - swap_texture_desc.SampleDesc.Count = 1; - swap_texture_desc.SampleDesc.Quality = 0; - swap_texture_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - swap_texture_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - // Can be sampled at any time, switch to render target when needed, then back. - if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, - &swap_texture_desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - nullptr, IID_PPV_ARGS(&swap_texture_)))) { - XELOGE("Failed to create the command processor front buffer"); + // Initialize compute pipelines for output with gamma ramp. + D3D12_ROOT_PARAMETER + apply_gamma_root_parameters[UINT(ApplyGammaRootParameter::kCount)]; + { + D3D12_ROOT_PARAMETER& apply_gamma_root_parameter_constants = + apply_gamma_root_parameters[UINT(ApplyGammaRootParameter::kConstants)]; + apply_gamma_root_parameter_constants.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + apply_gamma_root_parameter_constants.Constants.ShaderRegister = 0; + apply_gamma_root_parameter_constants.Constants.RegisterSpace = 0; + apply_gamma_root_parameter_constants.Constants.Num32BitValues = + sizeof(ApplyGammaConstants) / sizeof(uint32_t); + apply_gamma_root_parameter_constants.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE apply_gamma_root_descriptor_range_dest; + apply_gamma_root_descriptor_range_dest.RangeType = + D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + apply_gamma_root_descriptor_range_dest.NumDescriptors = 1; + apply_gamma_root_descriptor_range_dest.BaseShaderRegister = 0; + apply_gamma_root_descriptor_range_dest.RegisterSpace = 0; + apply_gamma_root_descriptor_range_dest.OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& apply_gamma_root_parameter_dest = + apply_gamma_root_parameters[UINT( + ApplyGammaRootParameter::kDestination)]; + apply_gamma_root_parameter_dest.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + apply_gamma_root_parameter_dest.DescriptorTable.NumDescriptorRanges = 1; + apply_gamma_root_parameter_dest.DescriptorTable.pDescriptorRanges = + &apply_gamma_root_descriptor_range_dest; + apply_gamma_root_parameter_dest.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE apply_gamma_root_descriptor_range_source; + apply_gamma_root_descriptor_range_source.RangeType = + D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + apply_gamma_root_descriptor_range_source.NumDescriptors = 1; + apply_gamma_root_descriptor_range_source.BaseShaderRegister = 0; + apply_gamma_root_descriptor_range_source.RegisterSpace = 0; + apply_gamma_root_descriptor_range_source.OffsetInDescriptorsFromTableStart = + 0; + { + D3D12_ROOT_PARAMETER& apply_gamma_root_parameter_source = + apply_gamma_root_parameters[UINT(ApplyGammaRootParameter::kSource)]; + apply_gamma_root_parameter_source.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + apply_gamma_root_parameter_source.DescriptorTable.NumDescriptorRanges = 1; + apply_gamma_root_parameter_source.DescriptorTable.pDescriptorRanges = + &apply_gamma_root_descriptor_range_source; + apply_gamma_root_parameter_source.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE apply_gamma_root_descriptor_range_ramp; + apply_gamma_root_descriptor_range_ramp.RangeType = + D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + apply_gamma_root_descriptor_range_ramp.NumDescriptors = 1; + apply_gamma_root_descriptor_range_ramp.BaseShaderRegister = 1; + apply_gamma_root_descriptor_range_ramp.RegisterSpace = 0; + apply_gamma_root_descriptor_range_ramp.OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& apply_gamma_root_parameter_gamma_ramp = + apply_gamma_root_parameters[UINT(ApplyGammaRootParameter::kRamp)]; + apply_gamma_root_parameter_gamma_ramp.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + apply_gamma_root_parameter_gamma_ramp.DescriptorTable.NumDescriptorRanges = + 1; + apply_gamma_root_parameter_gamma_ramp.DescriptorTable.pDescriptorRanges = + &apply_gamma_root_descriptor_range_ramp; + apply_gamma_root_parameter_gamma_ramp.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_ROOT_SIGNATURE_DESC apply_gamma_root_signature_desc; + apply_gamma_root_signature_desc.NumParameters = + UINT(ApplyGammaRootParameter::kCount); + apply_gamma_root_signature_desc.pParameters = apply_gamma_root_parameters; + apply_gamma_root_signature_desc.NumStaticSamplers = 0; + apply_gamma_root_signature_desc.pStaticSamplers = nullptr; + apply_gamma_root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + *(apply_gamma_root_signature_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateRootSignature(provider, + apply_gamma_root_signature_desc); + if (!apply_gamma_root_signature_) { + XELOGE("Failed to create the gamma ramp application root signature"); return false; } - device->GetCopyableFootprints(&swap_texture_desc, 0, 1, 0, - &swap_texture_copy_footprint_, nullptr, nullptr, - &swap_texture_copy_size_); - D3D12_DESCRIPTOR_HEAP_DESC swap_descriptor_heap_desc; - swap_descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - swap_descriptor_heap_desc.NumDescriptors = 1; - swap_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - swap_descriptor_heap_desc.NodeMask = 0; - if (FAILED(device->CreateDescriptorHeap( - &swap_descriptor_heap_desc, - IID_PPV_ARGS(&swap_texture_rtv_descriptor_heap_)))) { - XELOGE("Failed to create the command processor front buffer RTV heap"); + *(apply_gamma_table_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline( + device, shaders::apply_gamma_table_cs, + sizeof(shaders::apply_gamma_table_cs), + apply_gamma_root_signature_.Get()); + if (!apply_gamma_table_pipeline_) { + XELOGE( + "Failed to create the 256-entry table gamma ramp application compute " + "pipeline"); return false; } - swap_texture_rtv_ = - swap_texture_rtv_descriptor_heap_->GetCPUDescriptorHandleForHeapStart(); - D3D12_RENDER_TARGET_VIEW_DESC swap_rtv_desc; - swap_rtv_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat; - swap_rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - swap_rtv_desc.Texture2D.MipSlice = 0; - swap_rtv_desc.Texture2D.PlaneSlice = 0; - device->CreateRenderTargetView(swap_texture_, &swap_rtv_desc, - swap_texture_rtv_); - swap_descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - swap_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - if (FAILED(device->CreateDescriptorHeap( - &swap_descriptor_heap_desc, - IID_PPV_ARGS(&swap_texture_srv_descriptor_heap_)))) { - XELOGE("Failed to create the command processor front buffer SRV heap"); + *(apply_gamma_table_fxaa_luma_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline( + device, shaders::apply_gamma_table_fxaa_luma_cs, + sizeof(shaders::apply_gamma_table_fxaa_luma_cs), + apply_gamma_root_signature_.Get()); + if (!apply_gamma_table_fxaa_luma_pipeline_) { + XELOGE( + "Failed to create the 256-entry table gamma ramp application compute " + "pipeline with perceptual luma output"); + return false; + } + *(apply_gamma_pwl_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline( + device, shaders::apply_gamma_pwl_cs, + sizeof(shaders::apply_gamma_pwl_cs), + apply_gamma_root_signature_.Get()); + if (!apply_gamma_pwl_pipeline_) { + XELOGE("Failed to create the PWL gamma ramp application compute pipeline"); + return false; + } + *(apply_gamma_pwl_fxaa_luma_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline( + device, shaders::apply_gamma_pwl_fxaa_luma_cs, + sizeof(shaders::apply_gamma_pwl_fxaa_luma_cs), + apply_gamma_root_signature_.Get()); + if (!apply_gamma_pwl_fxaa_luma_pipeline_) { + XELOGE( + "Failed to create the PWL gamma ramp application compute pipeline with " + "perceptual luma output"); + return false; + } + + // Initialize compute pipelines for post-processing anti-aliasing. + D3D12_ROOT_PARAMETER fxaa_root_parameters[UINT(FxaaRootParameter::kCount)]; + { + D3D12_ROOT_PARAMETER& fxaa_root_parameter_constants = + fxaa_root_parameters[UINT(ApplyGammaRootParameter::kConstants)]; + fxaa_root_parameter_constants.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + fxaa_root_parameter_constants.Constants.ShaderRegister = 0; + fxaa_root_parameter_constants.Constants.RegisterSpace = 0; + fxaa_root_parameter_constants.Constants.Num32BitValues = + sizeof(FxaaConstants) / sizeof(uint32_t); + fxaa_root_parameter_constants.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE fxaa_root_descriptor_range_dest; + fxaa_root_descriptor_range_dest.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + fxaa_root_descriptor_range_dest.NumDescriptors = 1; + fxaa_root_descriptor_range_dest.BaseShaderRegister = 0; + fxaa_root_descriptor_range_dest.RegisterSpace = 0; + fxaa_root_descriptor_range_dest.OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& fxaa_root_parameter_dest = + fxaa_root_parameters[UINT(FxaaRootParameter::kDestination)]; + fxaa_root_parameter_dest.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + fxaa_root_parameter_dest.DescriptorTable.NumDescriptorRanges = 1; + fxaa_root_parameter_dest.DescriptorTable.pDescriptorRanges = + &fxaa_root_descriptor_range_dest; + fxaa_root_parameter_dest.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE fxaa_root_descriptor_range_source; + fxaa_root_descriptor_range_source.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + fxaa_root_descriptor_range_source.NumDescriptors = 1; + fxaa_root_descriptor_range_source.BaseShaderRegister = 0; + fxaa_root_descriptor_range_source.RegisterSpace = 0; + fxaa_root_descriptor_range_source.OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& fxaa_root_parameter_source = + fxaa_root_parameters[UINT(FxaaRootParameter::kSource)]; + fxaa_root_parameter_source.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + fxaa_root_parameter_source.DescriptorTable.NumDescriptorRanges = 1; + fxaa_root_parameter_source.DescriptorTable.pDescriptorRanges = + &fxaa_root_descriptor_range_source; + fxaa_root_parameter_source.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_STATIC_SAMPLER_DESC fxaa_root_sampler; + fxaa_root_sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + fxaa_root_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + fxaa_root_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + fxaa_root_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + fxaa_root_sampler.MipLODBias = 0.0f; + fxaa_root_sampler.MaxAnisotropy = 1; + fxaa_root_sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + fxaa_root_sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + fxaa_root_sampler.MinLOD = 0.0f; + fxaa_root_sampler.MaxLOD = 0.0f; + fxaa_root_sampler.ShaderRegister = 0; + fxaa_root_sampler.RegisterSpace = 0; + fxaa_root_sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + D3D12_ROOT_SIGNATURE_DESC fxaa_root_signature_desc; + fxaa_root_signature_desc.NumParameters = UINT(FxaaRootParameter::kCount); + fxaa_root_signature_desc.pParameters = fxaa_root_parameters; + fxaa_root_signature_desc.NumStaticSamplers = 1; + fxaa_root_signature_desc.pStaticSamplers = &fxaa_root_sampler; + fxaa_root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + *(fxaa_root_signature_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateRootSignature(provider, fxaa_root_signature_desc); + if (!fxaa_root_signature_) { + XELOGE("Failed to create the FXAA root signature"); + return false; + } + *(fxaa_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline(device, shaders::fxaa_cs, + sizeof(shaders::fxaa_cs), + fxaa_root_signature_.Get()); + if (!fxaa_pipeline_) { + XELOGE("Failed to create the FXAA compute pipeline"); + return false; + } + *(fxaa_extreme_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline(device, shaders::fxaa_extreme_cs, + sizeof(shaders::fxaa_extreme_cs), + fxaa_root_signature_.Get()); + if (!fxaa_pipeline_) { + XELOGE("Failed to create the extreme-quality FXAA compute pipeline"); return false; } - D3D12_SHADER_RESOURCE_VIEW_DESC swap_srv_desc; - swap_srv_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat; - swap_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - swap_srv_desc.Shader4ComponentMapping = - D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - swap_srv_desc.Texture2D.MostDetailedMip = 0; - swap_srv_desc.Texture2D.MipLevels = 1; - swap_srv_desc.Texture2D.PlaneSlice = 0; - swap_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; - device->CreateShaderResourceView( - swap_texture_, &swap_srv_desc, - swap_texture_srv_descriptor_heap_->GetCPUDescriptorHandleForHeapStart()); if (bindless_resources_used_) { // Create the system bindless descriptors once all resources are @@ -1471,11 +1557,11 @@ bool D3D12CommandProcessor::SetupContext() { view_bindless_heap_cpu_start_, uint32_t(SystemBindlessView::kEdramR32G32B32A32UintUAV)), 4); - // kGammaRampNormalSRV. + // kGammaRampTableSRV. WriteGammaRampSRV(false, provider.OffsetViewDescriptor( view_bindless_heap_cpu_start_, - uint32_t(SystemBindlessView::kGammaRampNormalSRV))); + uint32_t(SystemBindlessView::kGammaRampTableSRV))); // kGammaRampPWLSRV. WriteGammaRampSRV(true, provider.OffsetViewDescriptor( @@ -1501,35 +1587,29 @@ void D3D12CommandProcessor::ShutdownContext() { ui::d3d12::util::ReleaseAndNull(scratch_buffer_); scratch_buffer_size_ = 0; - for (auto& buffer_for_deletion : buffers_for_deletion_) { - buffer_for_deletion.first->Release(); + for (const std::pair& resource_for_deletion : + resources_for_deletion_) { + resource_for_deletion.second->Release(); } - buffers_for_deletion_.clear(); + resources_for_deletion_.clear(); - if (swap_texture_srv_descriptor_heap_ != nullptr) { - { - std::lock_guard lock(swap_state_.mutex); - swap_state_.pending = false; - swap_state_.front_buffer_texture = 0; - } - // TODO(Triang3l): Ensure this is synchronized. The display context may not - // exist at this point, so awaiting its fence doesn't always work. - swap_texture_srv_descriptor_heap_->Release(); - swap_texture_srv_descriptor_heap_ = nullptr; - } - ui::d3d12::util::ReleaseAndNull(swap_texture_rtv_descriptor_heap_); - ui::d3d12::util::ReleaseAndNull(swap_texture_); + fxaa_source_texture_submission_ = 0; + fxaa_source_texture_.Reset(); - // Don't need the data anymore, so zero range. - if (gamma_ramp_upload_mapping_ != nullptr) { - D3D12_RANGE gamma_ramp_written_range; - gamma_ramp_written_range.Begin = 0; - gamma_ramp_written_range.End = 0; - gamma_ramp_upload_->Unmap(0, &gamma_ramp_written_range); - gamma_ramp_upload_mapping_ = nullptr; - } - ui::d3d12::util::ReleaseAndNull(gamma_ramp_upload_); - ui::d3d12::util::ReleaseAndNull(gamma_ramp_texture_); + fxaa_extreme_pipeline_.Reset(); + fxaa_pipeline_.Reset(); + fxaa_root_signature_.Reset(); + + apply_gamma_pwl_fxaa_luma_pipeline_.Reset(); + apply_gamma_pwl_pipeline_.Reset(); + apply_gamma_table_fxaa_luma_pipeline_.Reset(); + apply_gamma_table_pipeline_.Reset(); + apply_gamma_root_signature_.Reset(); + + // Unmapping will be done implicitly by the destruction. + gamma_ramp_upload_buffer_mapping_ = nullptr; + gamma_ramp_upload_buffer_.Reset(); + gamma_ramp_buffer_.Reset(); pipeline_cache_.reset(); @@ -1596,6 +1676,8 @@ void D3D12CommandProcessor::ShutdownContext() { fence_completion_event_ = nullptr; } + device_removed_ = false; + CommandProcessor::ShutdownContext(); } @@ -1633,177 +1715,339 @@ void D3D12CommandProcessor::WriteRegister(uint32_t index, uint32_t value) { } else if (index == XE_GPU_REG_DC_LUT_PWL_DATA) { UpdateGammaRampValue(GammaRampType::kPWL, value); } else if (index == XE_GPU_REG_DC_LUT_30_COLOR) { - UpdateGammaRampValue(GammaRampType::kNormal, value); + UpdateGammaRampValue(GammaRampType::kTable, value); } else if (index == XE_GPU_REG_DC_LUT_RW_MODE) { gamma_ramp_rw_subindex_ = 0; } } -void D3D12CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, - uint32_t frontbuffer_width, - uint32_t frontbuffer_height) { +void D3D12CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, + uint32_t frontbuffer_width, + uint32_t frontbuffer_height) { // FIXME(Triang3l): frontbuffer_ptr is currently unreliable, in the trace // player it's set to 0, but it's not needed anyway since the fetch constant // contains the address. SCOPE_profile_cpu_f("gpu"); + ui::Presenter* presenter = graphics_system_->presenter(); + if (!presenter) { + return; + } + // In case the swap command is the only one in the frame. - BeginSubmission(true); - - auto device = GetD3D12Context().GetD3D12Provider().GetDevice(); - - // Upload the new gamma ramps, using the upload buffer for the current frame - // (will close the frame after this anyway, so can't write multiple times per - // frame). - uint32_t gamma_ramp_frame = uint32_t(frame_current_ % kQueueFrames); - if (dirty_gamma_ramp_normal_) { - const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& gamma_ramp_footprint = - gamma_ramp_footprints_[gamma_ramp_frame * 2]; - volatile uint32_t* mapping = reinterpret_cast( - gamma_ramp_upload_mapping_ + gamma_ramp_footprint.Offset); - for (uint32_t i = 0; i < 256; ++i) { - uint32_t value = gamma_ramp_.normal[i].value; - // Swap red and blue (535107D4 has settings allowing separate - // configuration). - mapping[i] = ((value & 1023) << 20) | (value & (1023 << 10)) | - ((value >> 20) & 1023); - } - PushTransitionBarrier(gamma_ramp_texture_, gamma_ramp_texture_state_, - D3D12_RESOURCE_STATE_COPY_DEST); - gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_COPY_DEST; - SubmitBarriers(); - D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; - location_source.pResource = gamma_ramp_upload_; - location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - location_source.PlacedFootprint = gamma_ramp_footprint; - location_dest.pResource = gamma_ramp_texture_; - location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - location_dest.SubresourceIndex = 0; - deferred_command_list_.CopyTexture(location_dest, location_source); - dirty_gamma_ramp_normal_ = false; - } - if (dirty_gamma_ramp_pwl_) { - const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& gamma_ramp_footprint = - gamma_ramp_footprints_[gamma_ramp_frame * 2 + 1]; - volatile uint32_t* mapping = reinterpret_cast( - gamma_ramp_upload_mapping_ + gamma_ramp_footprint.Offset); - for (uint32_t i = 0; i < 128; ++i) { - // TODO(Triang3l): Find a game to test if red and blue need to be swapped. - mapping[i] = (gamma_ramp_.pwl[i].values[0].base >> 6) | - (uint32_t(gamma_ramp_.pwl[i].values[1].base >> 6) << 10) | - (uint32_t(gamma_ramp_.pwl[i].values[2].base >> 6) << 20); - } - PushTransitionBarrier(gamma_ramp_texture_, gamma_ramp_texture_state_, - D3D12_RESOURCE_STATE_COPY_DEST); - gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_COPY_DEST; - SubmitBarriers(); - D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; - location_source.pResource = gamma_ramp_upload_; - location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - location_source.PlacedFootprint = gamma_ramp_footprint; - location_dest.pResource = gamma_ramp_texture_; - location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - location_dest.SubresourceIndex = 1; - deferred_command_list_.CopyTexture(location_dest, location_source); - dirty_gamma_ramp_pwl_ = false; + if (!BeginSubmission(true)) { + return; } + // Obtain the actual front buffer size to pass to RefreshGuestOutput, + // resolution-scaled if it's a resolve destination, or not otherwise. D3D12_SHADER_RESOURCE_VIEW_DESC swap_texture_srv_desc; xenos::TextureFormat frontbuffer_format; ID3D12Resource* swap_texture_resource = texture_cache_->RequestSwapTexture( swap_texture_srv_desc, frontbuffer_format); - if (swap_texture_resource) { - // This is according to D3D::InitializePresentationParameters from a game - // executable, which initializes the normal gamma ramp for 8_8_8_8 output - // and the PWL gamma ramp for 2_10_10_10. - bool use_pwl_gamma_ramp = - frontbuffer_format == xenos::TextureFormat::k_2_10_10_10 || - frontbuffer_format == xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16; - - bool descriptors_obtained; - ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_swap_texture; - ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_gamma_ramp; - if (bindless_resources_used_) { - descriptors_obtained = - RequestOneUseSingleViewDescriptors(1, &descriptor_swap_texture); - descriptor_gamma_ramp = GetSystemBindlessViewHandlePair( - use_pwl_gamma_ramp ? SystemBindlessView::kGammaRampPWLSRV - : SystemBindlessView::kGammaRampNormalSRV); - } else { - ui::d3d12::util::DescriptorCpuGpuHandlePair descriptors[2]; - descriptors_obtained = RequestOneUseSingleViewDescriptors(2, descriptors); - if (descriptors_obtained) { - descriptor_swap_texture = descriptors[0]; - descriptor_gamma_ramp = descriptors[1]; - WriteGammaRampSRV(use_pwl_gamma_ramp, descriptor_gamma_ramp.first); - } - } - if (descriptors_obtained) { - // Must not call anything that can change the descriptor heap from now on! - - // Create the swap texture descriptor. - device->CreateShaderResourceView(swap_texture_resource, - &swap_texture_srv_desc, - descriptor_swap_texture.first); - - // The swap texture is kept as an SRV because the graphics system may draw - // with it at any time. It's switched to RTV and back when needed. - PushTransitionBarrier(swap_texture_, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - D3D12_RESOURCE_STATE_RENDER_TARGET); - PushTransitionBarrier(gamma_ramp_texture_, gamma_ramp_texture_state_, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - SubmitBarriers(); - - auto swap_texture_size = GetSwapTextureSize(); - - // Draw the stretching rectangle. - render_target_cache_->InvalidateCommandListRenderTargets(); - deferred_command_list_.D3DOMSetRenderTargets(1, &swap_texture_rtv_, TRUE, - nullptr); - D3D12_VIEWPORT viewport; - viewport.TopLeftX = 0.0f; - viewport.TopLeftY = 0.0f; - viewport.Width = float(swap_texture_size.first); - viewport.Height = float(swap_texture_size.second); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 0.0f; - SetViewport(viewport); - D3D12_RECT scissor; - scissor.left = 0; - scissor.top = 0; - scissor.right = swap_texture_size.first; - scissor.bottom = swap_texture_size.second; - SetScissorRect(scissor); - D3D12GraphicsSystem* graphics_system = - static_cast(graphics_system_); - current_cached_pipeline_ = nullptr; - current_external_pipeline_ = nullptr; - current_graphics_root_signature_ = nullptr; - primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - graphics_system->StretchTextureToFrontBuffer( - descriptor_swap_texture.second, &descriptor_gamma_ramp.second, - use_pwl_gamma_ramp ? (1.0f / 128.0f) : (1.0f / 256.0f), - deferred_command_list_); - // Ending the current frame anyway, so no need to reset the current render - // targets when using ROV. - - PushTransitionBarrier(swap_texture_, D3D12_RESOURCE_STATE_RENDER_TARGET, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - // Don't care about graphics state because the frame is ending anyway. - auto swap_screen_size = GetSwapScreenSize(); - { - std::lock_guard lock(swap_state_.mutex); - swap_state_.width = swap_screen_size.first; - swap_state_.height = swap_screen_size.second; - swap_state_.front_buffer_texture = - reinterpret_cast(swap_texture_srv_descriptor_heap_); - } - } + if (!swap_texture_resource) { + return; } + D3D12_RESOURCE_DESC swap_texture_desc = swap_texture_resource->GetDesc(); + uint32_t resolution_scale_max = + std::max(texture_cache_->GetDrawResolutionScaleX(), + texture_cache_->GetDrawResolutionScaleY()); + presenter->RefreshGuestOutput( + uint32_t(swap_texture_desc.Width), uint32_t(swap_texture_desc.Height), + 1280 * resolution_scale_max, 720 * resolution_scale_max, + [this, &swap_texture_srv_desc, frontbuffer_format, swap_texture_resource, + &swap_texture_desc]( + ui::Presenter::GuestOutputRefreshContext& context) -> bool { + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); + + SwapPostEffect swap_post_effect = GetActualSwapPostEffect(); + bool use_fxaa = swap_post_effect == SwapPostEffect::kFxaa || + swap_post_effect == SwapPostEffect::kFxaaExtreme; + if (use_fxaa) { + // Make sure the texture of the correct size is available for FXAA. + if (fxaa_source_texture_) { + D3D12_RESOURCE_DESC fxaa_source_texture_desc = + fxaa_source_texture_->GetDesc(); + if (fxaa_source_texture_desc.Width != swap_texture_desc.Width || + fxaa_source_texture_desc.Height != swap_texture_desc.Height) { + if (submission_completed_ < fxaa_source_texture_submission_) { + fxaa_source_texture_->AddRef(); + resources_for_deletion_.emplace_back( + fxaa_source_texture_submission_, + fxaa_source_texture_.Get()); + } + fxaa_source_texture_.Reset(); + fxaa_source_texture_submission_ = 0; + } + } + if (!fxaa_source_texture_) { + D3D12_RESOURCE_DESC fxaa_source_texture_desc; + fxaa_source_texture_desc.Dimension = + D3D12_RESOURCE_DIMENSION_TEXTURE2D; + fxaa_source_texture_desc.Alignment = 0; + fxaa_source_texture_desc.Width = swap_texture_desc.Width; + fxaa_source_texture_desc.Height = swap_texture_desc.Height; + fxaa_source_texture_desc.DepthOrArraySize = 1; + fxaa_source_texture_desc.MipLevels = 1; + fxaa_source_texture_desc.Format = kFxaaSourceTextureFormat; + fxaa_source_texture_desc.SampleDesc.Count = 1; + fxaa_source_texture_desc.SampleDesc.Quality = 0; + fxaa_source_texture_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + fxaa_source_texture_desc.Flags = + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + if (FAILED(device->CreateCommittedResource( + &ui::d3d12::util::kHeapPropertiesDefault, + provider.GetHeapFlagCreateNotZeroed(), + &fxaa_source_texture_desc, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, nullptr, + IID_PPV_ARGS(&fxaa_source_texture_)))) { + XELOGE("Failed to create the FXAA input texture"); + swap_post_effect = SwapPostEffect::kNone; + use_fxaa = false; + } + } + } + + // This is according to D3D::InitializePresentationParameters from a + // game executable, which initializes the 256-entry table gamma ramp for + // 8_8_8_8 output and the PWL gamma ramp for 2_10_10_10. + bool use_pwl_gamma_ramp = + frontbuffer_format == xenos::TextureFormat::k_2_10_10_10 || + frontbuffer_format == + xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16; + + context.SetIs8bpc(!use_pwl_gamma_ramp && !use_fxaa); + + // Upload the new gamma ramp, using the upload buffer for the current + // frame (will close the frame after this anyway, so can't write + // multiple times per frame). + if (use_pwl_gamma_ramp ? dirty_gamma_ramp_pwl_ + : dirty_gamma_ramp_table_) { + uint32_t gamma_ramp_offset_bytes = use_pwl_gamma_ramp ? 256 * 4 : 0; + uint32_t gamma_ramp_upload_offset_bytes = + uint32_t(frame_current_ % kQueueFrames) * ((256 + 128 * 3) * 4) + + gamma_ramp_offset_bytes; + uint32_t gamma_ramp_size_bytes = + (use_pwl_gamma_ramp ? 128 * 3 : 256) * 4; + std::memcpy(gamma_ramp_upload_buffer_mapping_ + + gamma_ramp_upload_offset_bytes, + use_pwl_gamma_ramp + ? static_cast(gamma_ramp_.pwl) + : static_cast(gamma_ramp_.table), + gamma_ramp_size_bytes); + PushTransitionBarrier(gamma_ramp_buffer_.Get(), + gamma_ramp_buffer_state_, + D3D12_RESOURCE_STATE_COPY_DEST); + gamma_ramp_buffer_state_ = D3D12_RESOURCE_STATE_COPY_DEST; + SubmitBarriers(); + deferred_command_list_.D3DCopyBufferRegion( + gamma_ramp_buffer_.Get(), gamma_ramp_offset_bytes, + gamma_ramp_upload_buffer_.Get(), gamma_ramp_upload_offset_bytes, + gamma_ramp_size_bytes); + (use_pwl_gamma_ramp ? dirty_gamma_ramp_pwl_ + : dirty_gamma_ramp_table_) = false; + } + + // Destination, source, and if bindful, gamma ramp. + ui::d3d12::util::DescriptorCpuGpuHandlePair apply_gamma_descriptors[3]; + ui::d3d12::util::DescriptorCpuGpuHandlePair + apply_gamma_descriptor_gamma_ramp; + if (!RequestOneUseSingleViewDescriptors( + bindless_resources_used_ ? 2 : 3, apply_gamma_descriptors)) { + return false; + } + // Must not call anything that can change the descriptor heap from now + // on! + if (bindless_resources_used_) { + apply_gamma_descriptor_gamma_ramp = GetSystemBindlessViewHandlePair( + use_pwl_gamma_ramp ? SystemBindlessView::kGammaRampPWLSRV + : SystemBindlessView::kGammaRampTableSRV); + } else { + apply_gamma_descriptor_gamma_ramp = apply_gamma_descriptors[2]; + WriteGammaRampSRV(use_pwl_gamma_ramp, + apply_gamma_descriptor_gamma_ramp.first); + } + + ID3D12Resource* guest_output_resource = + static_cast< + ui::d3d12::D3D12Presenter::D3D12GuestOutputRefreshContext&>( + context) + .resource_uav_capable(); + + if (use_fxaa) { + fxaa_source_texture_submission_ = submission_current_; + } + + ID3D12Resource* apply_gamma_dest = + use_fxaa ? fxaa_source_texture_.Get() : guest_output_resource; + D3D12_RESOURCE_STATES apply_gamma_dest_initial_state = + use_fxaa ? D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE + : ui::d3d12::D3D12Presenter::kGuestOutputInternalState; + static_cast( + context) + .resource_uav_capable(); + PushTransitionBarrier(apply_gamma_dest, apply_gamma_dest_initial_state, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + // From now on, even in case of failure, apply_gamma_dest must be + // transitioned back to apply_gamma_dest_initial_state! + D3D12_UNORDERED_ACCESS_VIEW_DESC apply_gamma_dest_uav_desc; + apply_gamma_dest_uav_desc.Format = + use_fxaa ? kFxaaSourceTextureFormat + : ui::d3d12::D3D12Presenter::kGuestOutputFormat; + apply_gamma_dest_uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + apply_gamma_dest_uav_desc.Texture2D.MipSlice = 0; + apply_gamma_dest_uav_desc.Texture2D.PlaneSlice = 0; + device->CreateUnorderedAccessView(apply_gamma_dest, nullptr, + &apply_gamma_dest_uav_desc, + apply_gamma_descriptors[0].first); + + device->CreateShaderResourceView(swap_texture_resource, + &swap_texture_srv_desc, + apply_gamma_descriptors[1].first); + + PushTransitionBarrier(gamma_ramp_buffer_.Get(), + gamma_ramp_buffer_state_, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + gamma_ramp_buffer_state_ = + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + + deferred_command_list_.D3DSetComputeRootSignature( + apply_gamma_root_signature_.Get()); + ApplyGammaConstants apply_gamma_constants; + apply_gamma_constants.size[0] = uint32_t(swap_texture_desc.Width); + apply_gamma_constants.size[1] = uint32_t(swap_texture_desc.Height); + deferred_command_list_.D3DSetComputeRoot32BitConstants( + UINT(ApplyGammaRootParameter::kConstants), + sizeof(apply_gamma_constants) / sizeof(uint32_t), + &apply_gamma_constants, 0); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(ApplyGammaRootParameter::kDestination), + apply_gamma_descriptors[0].second); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(ApplyGammaRootParameter::kSource), + apply_gamma_descriptors[1].second); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(ApplyGammaRootParameter::kRamp), + apply_gamma_descriptor_gamma_ramp.second); + ID3D12PipelineState* apply_gamma_pipeline; + if (use_pwl_gamma_ramp) { + apply_gamma_pipeline = use_fxaa + ? apply_gamma_pwl_fxaa_luma_pipeline_.Get() + : apply_gamma_pwl_pipeline_.Get(); + } else { + apply_gamma_pipeline = + use_fxaa ? apply_gamma_table_fxaa_luma_pipeline_.Get() + : apply_gamma_table_pipeline_.Get(); + } + SetExternalPipeline(apply_gamma_pipeline); + SubmitBarriers(); + uint32_t group_count_x = (uint32_t(swap_texture_desc.Width) + 7) / 8; + uint32_t group_count_y = (uint32_t(swap_texture_desc.Height) + 7) / 8; + deferred_command_list_.D3DDispatch(group_count_x, group_count_y, 1); + + // Apply FXAA. + if (use_fxaa) { + // Destination and source. + ui::d3d12::util::DescriptorCpuGpuHandlePair fxaa_descriptors[2]; + if (!RequestOneUseSingleViewDescriptors( + uint32_t(xe::countof(fxaa_descriptors)), fxaa_descriptors)) { + // Failed to obtain descriptors for FXAA - just copy after gamma + // ramp application without applying FXAA. + PushTransitionBarrier(apply_gamma_dest, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + D3D12_RESOURCE_STATE_COPY_SOURCE); + PushTransitionBarrier( + guest_output_resource, + ui::d3d12::D3D12Presenter::kGuestOutputInternalState, + D3D12_RESOURCE_STATE_COPY_DEST); + SubmitBarriers(); + deferred_command_list_.D3DCopyResource(guest_output_resource, + apply_gamma_dest); + PushTransitionBarrier(apply_gamma_dest, + D3D12_RESOURCE_STATE_COPY_SOURCE, + apply_gamma_dest_initial_state); + PushTransitionBarrier( + guest_output_resource, D3D12_RESOURCE_STATE_COPY_DEST, + ui::d3d12::D3D12Presenter::kGuestOutputInternalState); + return false; + } else { + assert_true(apply_gamma_dest_initial_state == + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + PushTransitionBarrier(apply_gamma_dest, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + apply_gamma_dest_initial_state); + PushTransitionBarrier( + guest_output_resource, + ui::d3d12::D3D12Presenter::kGuestOutputInternalState, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + // From now on, even in case of failure, guest_output_resource must + // be transitioned back to kGuestOutputInternalState! + deferred_command_list_.D3DSetComputeRootSignature( + fxaa_root_signature_.Get()); + FxaaConstants fxaa_constants; + fxaa_constants.size[0] = uint32_t(swap_texture_desc.Width); + fxaa_constants.size[1] = uint32_t(swap_texture_desc.Height); + fxaa_constants.size_inv[0] = 1.0f / float(fxaa_constants.size[0]); + fxaa_constants.size_inv[1] = 1.0f / float(fxaa_constants.size[1]); + deferred_command_list_.D3DSetComputeRoot32BitConstants( + UINT(FxaaRootParameter::kConstants), + sizeof(fxaa_constants) / sizeof(uint32_t), &fxaa_constants, 0); + D3D12_UNORDERED_ACCESS_VIEW_DESC fxaa_dest_uav_desc; + fxaa_dest_uav_desc.Format = + ui::d3d12::D3D12Presenter::kGuestOutputFormat; + fxaa_dest_uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + fxaa_dest_uav_desc.Texture2D.MipSlice = 0; + fxaa_dest_uav_desc.Texture2D.PlaneSlice = 0; + device->CreateUnorderedAccessView(guest_output_resource, nullptr, + &fxaa_dest_uav_desc, + fxaa_descriptors[0].first); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(FxaaRootParameter::kDestination), + fxaa_descriptors[0].second); + D3D12_SHADER_RESOURCE_VIEW_DESC fxaa_source_srv_desc; + fxaa_source_srv_desc.Format = kFxaaSourceTextureFormat; + fxaa_source_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + fxaa_source_srv_desc.Shader4ComponentMapping = + D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + fxaa_source_srv_desc.Texture2D.MostDetailedMip = 0; + fxaa_source_srv_desc.Texture2D.MipLevels = 1; + fxaa_source_srv_desc.Texture2D.PlaneSlice = 0; + fxaa_source_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; + device->CreateShaderResourceView(fxaa_source_texture_.Get(), + &fxaa_source_srv_desc, + fxaa_descriptors[1].first); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(FxaaRootParameter::kSource), fxaa_descriptors[1].second); + SetExternalPipeline(swap_post_effect == SwapPostEffect::kFxaaExtreme + ? fxaa_extreme_pipeline_.Get() + : fxaa_pipeline_.Get()); + SubmitBarriers(); + deferred_command_list_.D3DDispatch(group_count_x, group_count_y, 1); + PushTransitionBarrier( + guest_output_resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + ui::d3d12::D3D12Presenter::kGuestOutputInternalState); + } + } else { + assert_true(apply_gamma_dest_initial_state == + ui::d3d12::D3D12Presenter::kGuestOutputInternalState); + PushTransitionBarrier(apply_gamma_dest, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + apply_gamma_dest_initial_state); + } + + // Need to submit all the commands before giving the image back to the + // presenter so it can submit its own commands for displaying it to the + // queue. + SubmitBarriers(); + EndSubmission(true); + return true; + }); + + // End the frame even if did not present for any reason (the image refresher + // was not called), to prevent leaking per-frame resources. EndSubmission(true); } @@ -1829,7 +2073,7 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, SCOPE_profile_cpu_f("gpu"); #endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES - ID3D12Device* device = GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = GetD3D12Provider().GetDevice(); const RegisterFile& regs = *register_file_; xenos::ModeControl edram_mode = regs.Get().edram_mode; @@ -1884,7 +2128,9 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, pixel_shader && pixel_shader->is_valid_memexport_used(); bool memexport_used = memexport_used_vertex || memexport_used_pixel; - BeginSubmission(true); + if (!BeginSubmission(true)) { + return false; + } // Process primitives. PrimitiveProcessor::ProcessingResult primitive_processing_result; @@ -2008,46 +2254,45 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, // Ensure vertex buffers are resident. // TODO(Triang3l): Cache residency for ranges in a way similar to how texture // validity is tracked. - uint64_t vertex_buffers_resident[2] = {}; - for (const Shader::VertexBinding& vertex_binding : - vertex_shader->vertex_bindings()) { - uint32_t vfetch_index = vertex_binding.fetch_constant; - if (vertex_buffers_resident[vfetch_index >> 6] & - (uint64_t(1) << (vfetch_index & 63))) { - continue; - } - const auto& vfetch_constant = regs.Get( - XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + vfetch_index * 2); - switch (vfetch_constant.type) { - case xenos::FetchConstantType::kVertex: - break; - case xenos::FetchConstantType::kInvalidVertex: - if (cvars::gpu_allow_invalid_fetch_constants) { + const Shader::ConstantRegisterMap& constant_map_vertex = + vertex_shader->constant_register_map(); + for (uint32_t i = 0; i < xe::countof(constant_map_vertex.vertex_fetch_bitmap); + ++i) { + uint32_t vfetch_bits_remaining = constant_map_vertex.vertex_fetch_bitmap[i]; + uint32_t j; + while (xe::bit_scan_forward(vfetch_bits_remaining, &j)) { + vfetch_bits_remaining &= ~(uint32_t(1) << j); + uint32_t vfetch_index = i * 32 + j; + const auto& vfetch_constant = regs.Get( + XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + vfetch_index * 2); + switch (vfetch_constant.type) { + case xenos::FetchConstantType::kVertex: break; - } - XELOGW( - "Vertex fetch constant {} ({:08X} {:08X}) has \"invalid\" type! " - "This " - "is incorrect behavior, but you can try bypassing this by " - "launching Xenia with --gpu_allow_invalid_fetch_constants=true.", - vfetch_index, vfetch_constant.dword_0, vfetch_constant.dword_1); - return false; - default: - XELOGW( - "Vertex fetch constant {} ({:08X} {:08X}) is completely invalid!", - vfetch_index, vfetch_constant.dword_0, vfetch_constant.dword_1); + case xenos::FetchConstantType::kInvalidVertex: + if (cvars::gpu_allow_invalid_fetch_constants) { + break; + } + XELOGW( + "Vertex fetch constant {} ({:08X} {:08X}) has \"invalid\" type! " + "This is incorrect behavior, but you can try bypassing this by " + "launching Xenia with --gpu_allow_invalid_fetch_constants=true.", + vfetch_index, vfetch_constant.dword_0, vfetch_constant.dword_1); + return false; + default: + XELOGW( + "Vertex fetch constant {} ({:08X} {:08X}) is completely invalid!", + vfetch_index, vfetch_constant.dword_0, vfetch_constant.dword_1); + return false; + } + if (!shared_memory_->RequestRange(vfetch_constant.address << 2, + vfetch_constant.size << 2)) { + XELOGE( + "Failed to request vertex buffer at 0x{:08X} (size {}) in the " + "shared memory", + vfetch_constant.address << 2, vfetch_constant.size << 2); return false; + } } - if (!shared_memory_->RequestRange(vfetch_constant.address << 2, - vfetch_constant.size << 2)) { - XELOGE( - "Failed to request vertex buffer at 0x{:08X} (size {}) in the shared " - "memory", - vfetch_constant.address << 2, vfetch_constant.size << 2); - return false; - } - vertex_buffers_resident[vfetch_index >> 6] |= uint64_t(1) - << (vfetch_index & 63); } // Gather memexport ranges and ensure the heaps for them are resident, and @@ -2350,7 +2595,9 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, } void D3D12CommandProcessor::InitializeTrace() { - BeginSubmission(false); + if (!BeginSubmission(false)) { + return; + } bool render_target_cache_submitted = render_target_cache_->InitializeTraceSubmitDownloads(); bool shared_memory_submitted = @@ -2371,7 +2618,9 @@ bool D3D12CommandProcessor::IssueCopy() { #if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES SCOPE_profile_cpu_f("gpu"); #endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES - BeginSubmission(true); + if (!BeginSubmission(true)) { + return false; + } uint32_t written_address, written_length; if (!render_target_cache_->Resolve(*memory_, *shared_memory_, *texture_cache_, written_address, written_length)) { @@ -2417,8 +2666,7 @@ void D3D12CommandProcessor::CheckSubmissionFence(uint64_t await_submission) { // outside of a submission, await explicitly. if (queue_operations_done_since_submission_signal_) { UINT64 fence_value = ++queue_operations_since_submission_fence_last_; - ID3D12CommandQueue* direct_queue = - GetD3D12Context().GetD3D12Provider().GetDirectQueue(); + ID3D12CommandQueue* direct_queue = GetD3D12Provider().GetDirectQueue(); if (SUCCEEDED( direct_queue->Signal(queue_operations_since_submission_fence_, fence_value) && @@ -2487,13 +2735,13 @@ void D3D12CommandProcessor::CheckSubmissionFence(uint64_t await_submission) { view_bindless_one_use_descriptors_.pop_front(); } - // Delete transient buffers marked for deletion. - while (!buffers_for_deletion_.empty()) { - if (buffers_for_deletion_.front().second > submission_completed_) { + // Delete transient resources marked for deletion. + while (!resources_for_deletion_.empty()) { + if (resources_for_deletion_.front().first > submission_completed_) { break; } - buffers_for_deletion_.front().first->Release(); - buffers_for_deletion_.pop_front(); + resources_for_deletion_.front().second->Release(); + resources_for_deletion_.pop_front(); } shared_memory_->CompletedSubmissionUpdated(); @@ -2503,14 +2751,28 @@ void D3D12CommandProcessor::CheckSubmissionFence(uint64_t await_submission) { render_target_cache_->CompletedSubmissionUpdated(); } -void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { +bool D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { #if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES SCOPE_profile_cpu_f("gpu"); #endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES + if (device_removed_) { + return false; + } + bool is_opening_frame = is_guest_command && !frame_open_; if (submission_open_ && !is_opening_frame) { - return; + return true; + } + + // Check if the device is still available. + ID3D12Device* device = GetD3D12Provider().GetDevice(); + HRESULT device_removed_reason = device->GetDeviceRemovedReason(); + if (FAILED(device_removed_reason)) { + device_removed_ = true; + graphics_system_->OnHostGpuLossFromAnyThread(device_removed_reason != + DXGI_ERROR_DEVICE_REMOVED); + return false; } // Check the fence - needed for all kinds of submissions (to reclaim transient @@ -2611,7 +2873,7 @@ void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { pix_capture_requested_.exchange(false, std::memory_order_relaxed); if (pix_capturing_) { IDXGraphicsAnalysis* graphics_analysis = - GetD3D12Context().GetD3D12Provider().GetGraphicsAnalysis(); + GetD3D12Provider().GetGraphicsAnalysis(); if (graphics_analysis != nullptr) { graphics_analysis->BeginCapture(); } @@ -2621,10 +2883,12 @@ void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { texture_cache_->BeginFrame(); } + + return true; } bool D3D12CommandProcessor::EndSubmission(bool is_swap) { - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); // Make sure there is a command allocator to write commands to. if (submission_open_ && !command_allocator_writable_first_) { @@ -2661,7 +2925,7 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) { // destroyed between frames. SubmitBarriers(); - auto direct_queue = provider.GetDirectQueue(); + ID3D12CommandQueue* direct_queue = provider.GetDirectQueue(); // Submit the deferred command list. // Only one deferred command list must be executed in the same @@ -3348,9 +3612,9 @@ void D3D12CommandProcessor::UpdateSystemConstantValues( bool D3D12CommandProcessor::UpdateBindings( const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader, ID3D12RootSignature* root_signature) { - auto& provider = GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); - auto& regs = *register_file_; + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); + const RegisterFile& regs = *register_file_; #if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES SCOPE_profile_cpu_f("gpu"); @@ -4179,8 +4443,8 @@ ID3D12Resource* D3D12CommandProcessor::RequestReadbackBuffer(uint32_t size) { } size = xe::align(size, kReadbackBufferSizeIncrement); if (size > readback_buffer_size_) { - auto& provider = GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); D3D12_RESOURCE_DESC buffer_desc; ui::d3d12::util::FillBufferResourceDesc(buffer_desc, size, D3D12_RESOURCE_FLAG_NONE); @@ -4202,16 +4466,23 @@ ID3D12Resource* D3D12CommandProcessor::RequestReadbackBuffer(uint32_t size) { void D3D12CommandProcessor::WriteGammaRampSRV( bool is_pwl, D3D12_CPU_DESCRIPTOR_HANDLE handle) const { - auto device = GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = GetD3D12Provider().GetDevice(); D3D12_SHADER_RESOURCE_VIEW_DESC desc; desc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - // 256-entry for normal, 128-entry for PWL. - desc.Texture1D.MostDetailedMip = is_pwl ? 1 : 0; - desc.Texture1D.MipLevels = 1; - desc.Texture1D.ResourceMinLODClamp = 0.0f; - device->CreateShaderResourceView(gamma_ramp_texture_, &desc, handle); + desc.Buffer.StructureByteStride = 0; + desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE; + if (is_pwl) { + desc.Format = DXGI_FORMAT_R16G16_UINT; + desc.Buffer.FirstElement = 256 * 4 / 4; + desc.Buffer.NumElements = 128 * 3; + } else { + desc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; + desc.Buffer.FirstElement = 0; + desc.Buffer.NumElements = 256; + } + device->CreateShaderResourceView(gamma_ramp_buffer_.Get(), &desc, handle); } } // namespace d3d12 diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.h b/src/xenia/gpu/d3d12/d3d12_command_processor.h index 3476a9ad8..abdd1fbda 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.h +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -32,8 +32,8 @@ #include "xenia/gpu/dxbc_shader_translator.h" #include "xenia/gpu/xenos.h" #include "xenia/kernel/kernel_state.h" -#include "xenia/ui/d3d12/d3d12_context.h" #include "xenia/ui/d3d12/d3d12_descriptor_heap_pool.h" +#include "xenia/ui/d3d12/d3d12_provider.h" #include "xenia/ui/d3d12/d3d12_upload_buffer_pool.h" #include "xenia/ui/d3d12/d3d12_util.h" @@ -58,8 +58,9 @@ class D3D12CommandProcessor : public CommandProcessor { void RestoreEdramSnapshot(const void* snapshot) override; - ui::d3d12::D3D12Context& GetD3D12Context() const { - return static_cast(*context_); + ui::d3d12::D3D12Provider& GetD3D12Provider() const { + return *static_cast( + graphics_system_->provider()); } // Returns the deferred drawing command list for the currently open @@ -153,7 +154,7 @@ class D3D12CommandProcessor : public CommandProcessor { kEdramR32G32UintUAV, kEdramR32G32B32A32UintUAV, - kGammaRampNormalSRV, + kGammaRampTableSRV, kGammaRampPWLSRV, // Beyond this point, SRVs are accessible to shaders through an unbounded @@ -210,16 +211,14 @@ class D3D12CommandProcessor : public CommandProcessor { // Returns the text to display in the GPU backend name in the window title. std::string GetWindowTitleText() const; - std::unique_ptr Capture(); - protected: bool SetupContext() override; void ShutdownContext() override; void WriteRegister(uint32_t index, uint32_t value) override; - void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height) override; + void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, + uint32_t frontbuffer_height) override; void OnPrimaryBufferEnd() override; @@ -321,8 +320,9 @@ class D3D12CommandProcessor : public CommandProcessor { void CheckSubmissionFence(uint64_t await_submission); // If is_guest_command is true, a new full frame - with full cleanup of // resources and, if needed, starting capturing - is opened if pending (as - // opposed to simply resuming after mid-frame synchronization). - void BeginSubmission(bool is_guest_command); + // opposed to simply resuming after mid-frame synchronization). Returns + // whether a submission is open currently and the device is not removed. + bool BeginSubmission(bool is_guest_command); // If is_swap is true, a full frame is closed - with, if needed, cache // clearing and stopping capturing. Returns whether the submission was done // successfully, if it has failed, leaves it open. @@ -380,6 +380,8 @@ class D3D12CommandProcessor : public CommandProcessor { void WriteGammaRampSRV(bool is_pwl, D3D12_CPU_DESCRIPTOR_HANDLE handle) const; + bool device_removed_ = false; + bool cache_clear_requested_ = false; HANDLE fence_completion_event_ = nullptr; @@ -497,42 +499,73 @@ class D3D12CommandProcessor : public CommandProcessor { std::unique_ptr texture_cache_; - // Mip 0 contains the normal gamma ramp (256 entries), mip 1 contains the PWL - // ramp (128 entries). DXGI_FORMAT_R10G10B10A2_UNORM 1D. - ID3D12Resource* gamma_ramp_texture_ = nullptr; - D3D12_RESOURCE_STATES gamma_ramp_texture_state_; + // Bytes 0x0...0x3FF - 256-entry R10G10B10X2 gamma ramp (red and blue must be + // read as swapped - 535107D4 has settings allowing separate configuration). + // Bytes 0x400...0x9FF - 128-entry PWL R16G16 gamma ramp (R - base, G - delta, + // low 6 bits of each are zero, 3 elements per entry). + // https://www.x.org/docs/AMD/old/42590_m76_rrg_1.01o.pdf + Microsoft::WRL::ComPtr gamma_ramp_buffer_; + D3D12_RESOURCE_STATES gamma_ramp_buffer_state_; // Upload buffer for an image that is the same as gamma_ramp_, but with // kQueueFrames array layers. - ID3D12Resource* gamma_ramp_upload_ = nullptr; - uint8_t* gamma_ramp_upload_mapping_ = nullptr; - D3D12_PLACED_SUBRESOURCE_FOOTPRINT gamma_ramp_footprints_[kQueueFrames * 2]; + Microsoft::WRL::ComPtr gamma_ramp_upload_buffer_; + uint8_t* gamma_ramp_upload_buffer_mapping_ = nullptr; - static constexpr uint32_t kSwapTextureWidth = 1280; - static constexpr uint32_t kSwapTextureHeight = 720; - std::pair GetSwapTextureSize() const { - return std::make_pair( - kSwapTextureWidth * texture_cache_->GetDrawResolutionScaleX(), - kSwapTextureHeight * texture_cache_->GetDrawResolutionScaleY()); - } - std::pair GetSwapScreenSize() const { - uint32_t resolution_scale = - std::max(texture_cache_->GetDrawResolutionScaleX(), - texture_cache_->GetDrawResolutionScaleY()); - return std::make_pair(kSwapTextureWidth * resolution_scale, - kSwapTextureHeight * resolution_scale); - } - ID3D12Resource* swap_texture_ = nullptr; - D3D12_PLACED_SUBRESOURCE_FOOTPRINT swap_texture_copy_footprint_; - UINT64 swap_texture_copy_size_; - ID3D12DescriptorHeap* swap_texture_rtv_descriptor_heap_ = nullptr; - D3D12_CPU_DESCRIPTOR_HANDLE swap_texture_rtv_; - ID3D12DescriptorHeap* swap_texture_srv_descriptor_heap_ = nullptr; + struct ApplyGammaConstants { + uint32_t size[2]; + }; + enum class ApplyGammaRootParameter : UINT { + kConstants, + kDestination, + kSource, + kRamp, + + kCount, + }; + Microsoft::WRL::ComPtr apply_gamma_root_signature_; + Microsoft::WRL::ComPtr apply_gamma_table_pipeline_; + Microsoft::WRL::ComPtr + apply_gamma_table_fxaa_luma_pipeline_; + Microsoft::WRL::ComPtr apply_gamma_pwl_pipeline_; + Microsoft::WRL::ComPtr + apply_gamma_pwl_fxaa_luma_pipeline_; + + struct FxaaConstants { + uint32_t size[2]; + float size_inv[2]; + }; + enum class FxaaRootParameter : UINT { + kConstants, + kDestination, + kSource, + + kCount, + }; + Microsoft::WRL::ComPtr fxaa_root_signature_; + Microsoft::WRL::ComPtr fxaa_pipeline_; + Microsoft::WRL::ComPtr fxaa_extreme_pipeline_; + + // PWL gamma ramp can result in values with more precision than 10bpc. Though + // those sub-10bpc bits don't have any noticeable visual effect, so normally + // R10G10B10A2_UNORM is enough. But what's the most important is that for the + // original FXAA shader, the luma needs to be written to the alpha channel. + // For simplicity (to avoid modifying the FXAA shader and adding more texture + // fetches into it), and for the highest quality (preserving all 13 bits that + // may be generated by applying the PWL gamma ramp with an increment of 2^3, + // and also leaving some space for the result of applying fractional weights + // to calculate the luma), using R16G16B16A16_UNORM instead of + // R10G10B10X2_UNORM with a separate alpha texture. + static constexpr DXGI_FORMAT kFxaaSourceTextureFormat = + DXGI_FORMAT_R16G16B16A16_UNORM; + // Kept in NON_PIXEL_SHADER_RESOURCE state. + Microsoft::WRL::ComPtr fxaa_source_texture_; + uint64_t fxaa_source_texture_submission_ = 0; // Unsubmitted barrier batch. std::vector barriers_; // , sorted by the submission number. - std::deque> buffers_for_deletion_; + std::deque> resources_for_deletion_; static constexpr uint32_t kScratchBufferSizeIncrement = 16 * 1024 * 1024; ID3D12Resource* scratch_buffer_ = nullptr; diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc index 411e95ce5..b4e0d025d 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc @@ -22,13 +22,6 @@ namespace xe { namespace gpu { namespace d3d12 { -// Generated with `xb buildshaders`. -namespace shaders { -#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h" -#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h" -#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h" -} // namespace shaders - D3D12GraphicsSystem::D3D12GraphicsSystem() {} D3D12GraphicsSystem::~D3D12GraphicsSystem() {} @@ -48,198 +41,11 @@ std::string D3D12GraphicsSystem::name() const { X_STATUS D3D12GraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) { + ui::WindowedAppContext* app_context, + bool is_surface_required) { provider_ = xe::ui::d3d12::D3D12Provider::Create(); - auto d3d12_provider = static_cast(provider()); - auto device = d3d12_provider->GetDevice(); - - auto result = GraphicsSystem::Setup(processor, kernel_state, target_window); - if (result != X_STATUS_SUCCESS) { - return result; - } - - if (target_window) { - display_context_ = reinterpret_cast( - target_window->context()); - } - - // Create the stretch pipeline root signature, with 1 parameter (source - // texture) for raw stretch and 3 parameters (source texture, gamma ramp LUT, - // inverse of the size of the gamma ramp LUT) for gamma-correcting stretch. - // Raw. - D3D12_ROOT_PARAMETER stretch_root_parameters[3]; - stretch_root_parameters[0].ParameterType = - D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - stretch_root_parameters[0].DescriptorTable.NumDescriptorRanges = 1; - D3D12_DESCRIPTOR_RANGE stretch_root_texture_range; - stretch_root_texture_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - stretch_root_texture_range.NumDescriptors = 1; - stretch_root_texture_range.BaseShaderRegister = 0; - stretch_root_texture_range.RegisterSpace = 0; - stretch_root_texture_range.OffsetInDescriptorsFromTableStart = 0; - stretch_root_parameters[0].DescriptorTable.pDescriptorRanges = - &stretch_root_texture_range; - stretch_root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - D3D12_STATIC_SAMPLER_DESC stretch_sampler_desc; - stretch_sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; - stretch_sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - stretch_sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - stretch_sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - stretch_sampler_desc.MipLODBias = 0.0f; - stretch_sampler_desc.MaxAnisotropy = 1; - stretch_sampler_desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; - stretch_sampler_desc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; - stretch_sampler_desc.MinLOD = 0.0f; - stretch_sampler_desc.MaxLOD = 0.0f; - stretch_sampler_desc.ShaderRegister = 0; - stretch_sampler_desc.RegisterSpace = 0; - stretch_sampler_desc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - D3D12_ROOT_SIGNATURE_DESC stretch_root_desc; - stretch_root_desc.NumParameters = 1; - stretch_root_desc.pParameters = stretch_root_parameters; - stretch_root_desc.NumStaticSamplers = 1; - stretch_root_desc.pStaticSamplers = &stretch_sampler_desc; - stretch_root_desc.Flags = - D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS; - stretch_root_signature_ = - ui::d3d12::util::CreateRootSignature(*d3d12_provider, stretch_root_desc); - if (stretch_root_signature_ == nullptr) { - XELOGE("Failed to create the front buffer stretch root signature"); - return X_STATUS_UNSUCCESSFUL; - } - // Gamma. - stretch_root_parameters[1].ParameterType = - D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - stretch_root_parameters[1].DescriptorTable.NumDescriptorRanges = 1; - D3D12_DESCRIPTOR_RANGE stretch_root_gamma_ramp_range; - stretch_root_gamma_ramp_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - stretch_root_gamma_ramp_range.NumDescriptors = 1; - stretch_root_gamma_ramp_range.BaseShaderRegister = 1; - stretch_root_gamma_ramp_range.RegisterSpace = 0; - stretch_root_gamma_ramp_range.OffsetInDescriptorsFromTableStart = 0; - stretch_root_parameters[1].DescriptorTable.pDescriptorRanges = - &stretch_root_gamma_ramp_range; - stretch_root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - stretch_root_parameters[2].ParameterType = - D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; - stretch_root_parameters[2].Constants.ShaderRegister = 0; - stretch_root_parameters[2].Constants.RegisterSpace = 0; - stretch_root_parameters[2].Constants.Num32BitValues = 1; - stretch_root_parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - stretch_root_desc.NumParameters = 3; - stretch_root_desc.pParameters = stretch_root_parameters; - stretch_gamma_root_signature_ = - ui::d3d12::util::CreateRootSignature(*d3d12_provider, stretch_root_desc); - if (stretch_gamma_root_signature_ == nullptr) { - XELOGE( - "Failed to create the gamma-correcting front buffer stretch root " - "signature"); - stretch_root_signature_->Release(); - stretch_root_signature_ = nullptr; - return X_STATUS_UNSUCCESSFUL; - } - - // Create the stretch pipelines. - D3D12_GRAPHICS_PIPELINE_STATE_DESC stretch_pipeline_desc = {}; - stretch_pipeline_desc.pRootSignature = stretch_root_signature_; - stretch_pipeline_desc.VS.pShaderBytecode = shaders::fullscreen_tc_vs; - stretch_pipeline_desc.VS.BytecodeLength = sizeof(shaders::fullscreen_tc_vs); - stretch_pipeline_desc.PS.pShaderBytecode = shaders::stretch_ps; - stretch_pipeline_desc.PS.BytecodeLength = sizeof(shaders::stretch_ps); - // The shader will set alpha to 1, don't use output-merger to preserve it. - stretch_pipeline_desc.BlendState.RenderTarget[0].RenderTargetWriteMask = - D3D12_COLOR_WRITE_ENABLE_ALL; - stretch_pipeline_desc.SampleMask = UINT_MAX; - stretch_pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; - stretch_pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; - stretch_pipeline_desc.RasterizerState.DepthClipEnable = TRUE; - stretch_pipeline_desc.PrimitiveTopologyType = - D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - stretch_pipeline_desc.NumRenderTargets = 1; - stretch_pipeline_desc.RTVFormats[0] = - ui::d3d12::D3D12Context::kSwapChainFormat; - stretch_pipeline_desc.SampleDesc.Count = 1; - if (FAILED(device->CreateGraphicsPipelineState( - &stretch_pipeline_desc, IID_PPV_ARGS(&stretch_pipeline_)))) { - XELOGE("Failed to create the front buffer stretch pipeline"); - stretch_gamma_root_signature_->Release(); - stretch_gamma_root_signature_ = nullptr; - stretch_root_signature_->Release(); - stretch_root_signature_ = nullptr; - return X_STATUS_UNSUCCESSFUL; - } - stretch_pipeline_desc.pRootSignature = stretch_gamma_root_signature_; - stretch_pipeline_desc.PS.pShaderBytecode = shaders::stretch_gamma_ps; - stretch_pipeline_desc.PS.BytecodeLength = sizeof(shaders::stretch_gamma_ps); - if (FAILED(device->CreateGraphicsPipelineState( - &stretch_pipeline_desc, IID_PPV_ARGS(&stretch_gamma_pipeline_)))) { - XELOGE( - "Failed to create the gamma-correcting front buffer stretch pipeline"); - stretch_pipeline_->Release(); - stretch_pipeline_ = nullptr; - stretch_gamma_root_signature_->Release(); - stretch_gamma_root_signature_ = nullptr; - stretch_root_signature_->Release(); - stretch_root_signature_ = nullptr; - return X_STATUS_UNSUCCESSFUL; - } - - return X_STATUS_SUCCESS; -} - -void D3D12GraphicsSystem::Shutdown() { - ui::d3d12::util::ReleaseAndNull(stretch_gamma_pipeline_); - ui::d3d12::util::ReleaseAndNull(stretch_pipeline_); - ui::d3d12::util::ReleaseAndNull(stretch_gamma_root_signature_); - ui::d3d12::util::ReleaseAndNull(stretch_root_signature_); - - GraphicsSystem::Shutdown(); -} - -std::unique_ptr D3D12GraphicsSystem::Capture() { - auto d3d12_command_processor = - static_cast(command_processor()); - if (!d3d12_command_processor) { - return nullptr; - } - return d3d12_command_processor->Capture(); -} - -void D3D12GraphicsSystem::StretchTextureToFrontBuffer( - D3D12_GPU_DESCRIPTOR_HANDLE handle, - D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size, - ID3D12GraphicsCommandList* command_list) { - if (gamma_ramp_handle != nullptr) { - command_list->SetPipelineState(stretch_gamma_pipeline_); - command_list->SetGraphicsRootSignature(stretch_gamma_root_signature_); - command_list->SetGraphicsRootDescriptorTable(1, *gamma_ramp_handle); - command_list->SetGraphicsRoot32BitConstants(2, 1, &gamma_ramp_inv_size, 0); - } else { - command_list->SetPipelineState(stretch_pipeline_); - command_list->SetGraphicsRootSignature(stretch_root_signature_); - } - command_list->SetGraphicsRootDescriptorTable(0, handle); - command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - command_list->DrawInstanced(3, 1, 0, 0); -} - -void D3D12GraphicsSystem::StretchTextureToFrontBuffer( - D3D12_GPU_DESCRIPTOR_HANDLE handle, - D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size, - DeferredCommandList& command_list) { - if (gamma_ramp_handle != nullptr) { - command_list.D3DSetPipelineState(stretch_gamma_pipeline_); - command_list.D3DSetGraphicsRootSignature(stretch_gamma_root_signature_); - command_list.D3DSetGraphicsRootDescriptorTable(1, *gamma_ramp_handle); - command_list.D3DSetGraphicsRoot32BitConstants(2, 1, &gamma_ramp_inv_size, - 0); - } else { - command_list.D3DSetPipelineState(stretch_pipeline_); - command_list.D3DSetGraphicsRootSignature(stretch_root_signature_); - } - command_list.D3DSetGraphicsRootDescriptorTable(0, handle); - command_list.D3DIASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - command_list.D3DDrawInstanced(3, 1, 0, 0); + return GraphicsSystem::Setup(processor, kernel_state, app_context, + is_surface_required); } std::unique_ptr @@ -248,69 +54,6 @@ D3D12GraphicsSystem::CreateCommandProcessor() { new D3D12CommandProcessor(this, kernel_state_)); } -void D3D12GraphicsSystem::Swap(xe::ui::UIEvent* e) { - if (display_context_->WasLost()) { - // We're crashing. Cheese it. - return; - } - - if (!command_processor_) { - return; - } - - auto& swap_state = command_processor_->swap_state(); - ID3D12DescriptorHeap* swap_srv_heap; - { - std::lock_guard lock(swap_state.mutex); - swap_state.pending = false; - swap_srv_heap = reinterpret_cast( - swap_state.front_buffer_texture); - } - if (swap_srv_heap == nullptr) { - // Not ready yet. - return; - } - - uint32_t window_width, window_height; - display_context_->GetSwapChainSize(window_width, window_height); - - int32_t target_x, target_y; - uint32_t target_width, target_height; - draw_util::GetPresentArea(swap_state.width, swap_state.height, window_width, - window_height, target_x, target_y, target_width, - target_height); - // For safety. - target_x = clamp(target_x, int32_t(D3D12_VIEWPORT_BOUNDS_MIN), - int32_t(D3D12_VIEWPORT_BOUNDS_MAX)); - target_y = clamp(target_y, int32_t(D3D12_VIEWPORT_BOUNDS_MIN), - int32_t(D3D12_VIEWPORT_BOUNDS_MAX)); - target_width = std::min( - target_width, uint32_t(int32_t(D3D12_VIEWPORT_BOUNDS_MAX) - target_x)); - target_height = std::min( - target_height, uint32_t(int32_t(D3D12_VIEWPORT_BOUNDS_MAX) - target_y)); - - auto command_list = display_context_->GetSwapCommandList(); - // Assuming the window has already been cleared to the needed letterbox color. - D3D12_VIEWPORT viewport; - viewport.TopLeftX = float(target_x); - viewport.TopLeftY = float(target_y); - viewport.Width = float(target_width); - viewport.Height = float(target_height); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 0.0f; - command_list->RSSetViewports(1, &viewport); - D3D12_RECT scissor; - scissor.left = 0; - scissor.top = 0; - scissor.right = window_width; - scissor.bottom = window_height; - command_list->RSSetScissorRects(1, &scissor); - command_list->SetDescriptorHeaps(1, &swap_srv_heap); - StretchTextureToFrontBuffer( - swap_srv_heap->GetGPUDescriptorHandleForHeapStart(), nullptr, 0.0f, - command_list); -} - } // namespace d3d12 } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.h b/src/xenia/gpu/d3d12/d3d12_graphics_system.h index 00faeb34f..249cc3ffa 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.h +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.h @@ -15,7 +15,6 @@ #include "xenia/gpu/command_processor.h" #include "xenia/gpu/d3d12/deferred_command_list.h" #include "xenia/gpu/graphics_system.h" -#include "xenia/ui/d3d12/d3d12_context.h" namespace xe { namespace gpu { @@ -31,37 +30,11 @@ class D3D12GraphicsSystem : public GraphicsSystem { std::string name() const override; X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) override; - void Shutdown() override; - - std::unique_ptr Capture() override; - - // Draws a texture covering the entire viewport to the render target currently - // bound on the specified command list (in D3D12Context::kSwapChainFormat). - // This changes the current pipeline, graphics root signature and primitive - // topology. The gamma ramp texture must be 1D if present at all, for linear - // space, pass nullptr as the gamma ramp. - void StretchTextureToFrontBuffer( - D3D12_GPU_DESCRIPTOR_HANDLE handle, - D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size, - ID3D12GraphicsCommandList* command_list); - void StretchTextureToFrontBuffer( - D3D12_GPU_DESCRIPTOR_HANDLE handle, - D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size, - DeferredCommandList& command_list); + ui::WindowedAppContext* app_context, + bool is_surface_required) override; protected: std::unique_ptr CreateCommandProcessor() override; - - void Swap(xe::ui::UIEvent* e) override; - - private: - ui::d3d12::D3D12Context* display_context_ = nullptr; - - ID3D12RootSignature* stretch_root_signature_ = nullptr; - ID3D12RootSignature* stretch_gamma_root_signature_ = nullptr; - ID3D12PipelineState* stretch_pipeline_ = nullptr; - ID3D12PipelineState* stretch_gamma_pipeline_ = nullptr; }; } // namespace d3d12 diff --git a/src/xenia/gpu/d3d12/d3d12_primitive_processor.cc b/src/xenia/gpu/d3d12/d3d12_primitive_processor.cc index ec1e576b0..a806546a1 100644 --- a/src/xenia/gpu/d3d12/d3d12_primitive_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_primitive_processor.cc @@ -33,7 +33,7 @@ bool D3D12PrimitiveProcessor::Initialize() { return false; } frame_index_buffer_pool_ = std::make_unique( - command_processor_.GetD3D12Context().GetD3D12Provider(), + command_processor_.GetD3D12Provider(), std::max(size_t(kMinRequiredConvertedIndexBufferSize), ui::GraphicsUploadBufferPool::kDefaultPageSize)); return true; @@ -90,7 +90,7 @@ bool D3D12PrimitiveProcessor::InitializeBuiltin16BitIndexBuffer( assert_null(builtin_index_buffer_upload_); const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); D3D12_RESOURCE_DESC resource_desc; diff --git a/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc b/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc index d72e37428..61b8bb83f 100644 --- a/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc +++ b/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc @@ -215,7 +215,7 @@ D3D12RenderTargetCache::~D3D12RenderTargetCache() { Shutdown(true); } bool D3D12RenderTargetCache::Initialize() { const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); if (cvars::render_target_path_d3d12 == "rtv") { @@ -1298,7 +1298,7 @@ bool D3D12RenderTargetCache::Update(bool is_rasterization_done, void D3D12RenderTargetCache::WriteEdramRawSRVDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE handle) { const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, @@ -1311,7 +1311,7 @@ void D3D12RenderTargetCache::WriteEdramRawSRVDescriptor( void D3D12RenderTargetCache::WriteEdramRawUAVDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE handle) { const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, @@ -1339,7 +1339,7 @@ void D3D12RenderTargetCache::WriteEdramUintPow2SRVDescriptor( return; } const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, @@ -1366,7 +1366,7 @@ void D3D12RenderTargetCache::WriteEdramUintPow2UAVDescriptor( return; } const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, @@ -1668,8 +1668,9 @@ bool D3D12RenderTargetCache::InitializeTraceSubmitDownloads() { ui::d3d12::util::FillBufferResourceDesc(edram_snapshot_download_buffer_desc, xenos::kEdramSizeBytes, D3D12_RESOURCE_FLAG_NONE); - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesReadback, provider.GetHeapFlagCreateNotZeroed(), @@ -1721,7 +1722,8 @@ void D3D12RenderTargetCache::RestoreEdramSnapshot(const void* snapshot) { // Create the buffer - will be used for copying to either a 32-bit 1280x2048 // render target or the EDRAM buffer. - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); if (!edram_snapshot_restore_pool_) { edram_snapshot_restore_pool_ = std::make_unique( @@ -1966,8 +1968,7 @@ DXGI_FORMAT D3D12RenderTargetCache::GetDepthSRVStencilDXGIFormat( RenderTargetCache::RenderTarget* D3D12RenderTargetCache::CreateRenderTarget( RenderTargetKey key) { - ID3D12Device* device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); D3D12_RESOURCE_DESC resource_desc; resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; @@ -4345,8 +4346,7 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) { // *************************************************************************** ID3D12PipelineState* const* pipelines; - ID3D12Device* device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); D3D12_INPUT_ELEMENT_DESC pipeline_input_element_desc; pipeline_input_element_desc.SemanticName = "POSITION"; pipeline_input_element_desc.SemanticIndex = 0; @@ -4516,7 +4516,7 @@ void D3D12RenderTargetCache::PerformTransfersAndResolveClears( assert_true(GetPath() == Path::kHostRenderTargets); const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); uint64_t current_submission = command_processor_.GetCurrentSubmission(); DeferredCommandList& command_list = @@ -6476,8 +6476,8 @@ ID3D12PipelineState* D3D12RenderTargetCache::GetOrCreateDumpPipeline( // Pipeline // *************************************************************************** ID3D12PipelineState* pipeline = ui::d3d12::util::CreateComputePipeline( - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(), - built_shader_.data(), built_shader_size_bytes, + command_processor_.GetD3D12Provider().GetDevice(), built_shader_.data(), + built_shader_size_bytes, key.is_depth ? dump_root_signature_depth_ : dump_root_signature_color_); const char* format_name = key.is_depth @@ -6561,7 +6561,7 @@ void D3D12RenderTargetCache::DumpRenderTargets(uint32_t dump_base, // 32bpp and 64bpp. size_t edram_uav_indices[2] = {SIZE_MAX, SIZE_MAX}; const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); if (!bindless_resources_used_) { if (any_sources_32bpp_64bpp[0]) { edram_uav_indices[0] = current_temporary_descriptors_cpu_.size(); diff --git a/src/xenia/gpu/d3d12/d3d12_shared_memory.cc b/src/xenia/gpu/d3d12/d3d12_shared_memory.cc index fd521da54..e946a3319 100644 --- a/src/xenia/gpu/d3d12/d3d12_shared_memory.cc +++ b/src/xenia/gpu/d3d12/d3d12_shared_memory.cc @@ -43,7 +43,7 @@ bool D3D12SharedMemory::Initialize() { InitializeCommon(); const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); D3D12_RESOURCE_DESC buffer_desc; @@ -215,8 +215,9 @@ void D3D12SharedMemory::CommitUAVWritesAndTransitionBuffer( void D3D12SharedMemory::WriteRawSRVDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE handle) { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, provider.OffsetViewDescriptor(buffer_descriptor_heap_start_, @@ -226,8 +227,9 @@ void D3D12SharedMemory::WriteRawSRVDescriptor( void D3D12SharedMemory::WriteRawUAVDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE handle) { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, provider.OffsetViewDescriptor(buffer_descriptor_heap_start_, @@ -252,8 +254,9 @@ void D3D12SharedMemory::WriteUintPow2SRVDescriptor( assert_unhandled_case(element_size_bytes_pow2); return; } - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, provider.OffsetViewDescriptor(buffer_descriptor_heap_start_, @@ -278,8 +281,9 @@ void D3D12SharedMemory::WriteUintPow2UAVDescriptor( assert_unhandled_case(element_size_bytes_pow2); return; } - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, provider.OffsetViewDescriptor(buffer_descriptor_heap_start_, @@ -298,8 +302,9 @@ bool D3D12SharedMemory::InitializeTraceSubmitDownloads() { ui::d3d12::util::FillBufferResourceDesc( download_buffer_desc, download_page_count << page_size_log2(), D3D12_RESOURCE_FLAG_NONE); - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesReadback, provider.GetHeapFlagCreateNotZeroed(), &download_buffer_desc, @@ -365,7 +370,7 @@ bool D3D12SharedMemory::AllocateSparseHostGpuMemoryRange( << host_gpu_memory_sparse_granularity_log2(); const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); ID3D12CommandQueue* direct_queue = provider.GetDirectQueue(); diff --git a/src/xenia/gpu/d3d12/deferred_command_list.h b/src/xenia/gpu/d3d12/deferred_command_list.h index a21d0c3c4..22b4fc5da 100644 --- a/src/xenia/gpu/d3d12/deferred_command_list.h +++ b/src/xenia/gpu/d3d12/deferred_command_list.h @@ -16,6 +16,7 @@ #include #include "xenia/base/assert.h" +#include "xenia/base/literals.h" #include "xenia/base/math.h" #include "xenia/ui/d3d12/d3d12_api.h" @@ -23,12 +24,14 @@ namespace xe { namespace gpu { namespace d3d12 { +using namespace xe::literals; + class D3D12CommandProcessor; class DeferredCommandList { public: DeferredCommandList(const D3D12CommandProcessor& command_processor, - size_t initial_size_bytes = 1024 * 1024); + size_t initial_size_bytes = 1_MiB); void Reset(); void Execute(ID3D12GraphicsCommandList* command_list, diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index 3eb63f172..3a0cb3313 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -87,7 +87,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor, register_file_(register_file), render_target_cache_(render_target_cache), bindless_resources_used_(bindless_resources_used) { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); bool edram_rov_used = render_target_cache.GetPath() == RenderTargetCache::Path::kPixelShaderInterlock; @@ -109,7 +110,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor, PipelineCache::~PipelineCache() { Shutdown(); } bool PipelineCache::Initialize() { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); // Initialize the command processor thread DXIL objects. dxbc_converter_ = nullptr; @@ -414,7 +416,8 @@ void PipelineCache::InitializeShaderStorage( std::mutex shaders_failed_to_translate_mutex; std::vector shaders_failed_to_translate; auto shader_translation_thread_function = [&]() { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); StringBuffer ucode_disasm_buffer; DxbcShaderTranslator translator( provider.GetAdapterVendorID(), bindless_resources_used_, @@ -700,37 +703,39 @@ void PipelineCache::InitializeShaderStorage( ++pipelines_created; } - CreateQueuedPipelinesOnProcessorThread(); - if (creation_threads_.size() > creation_thread_original_count) { - { - std::lock_guard lock(creation_request_lock_); - creation_threads_shutdown_from_ = creation_thread_original_count; - // Assuming the queue is empty because of - // CreateQueuedPipelinesOnProcessorThread. - } - creation_request_cond_.notify_all(); - while (creation_threads_.size() > creation_thread_original_count) { - xe::threading::Wait(creation_threads_.back().get(), false); - creation_threads_.pop_back(); - } - bool await_creation_completion_event; - { - // Cleanup so additional threads can be created later again. - std::lock_guard lock(creation_request_lock_); - creation_threads_shutdown_from_ = SIZE_MAX; - // If the invocation is blocking, all the shader storage initialization - // is expected to be done before proceeding, to avoid latency in the - // command processor after the invocation. - await_creation_completion_event = - blocking && creation_threads_busy_ != 0; - if (await_creation_completion_event) { - creation_completion_event_->Reset(); - creation_completion_set_event_ = true; + if (!creation_threads_.empty()) { + CreateQueuedPipelinesOnProcessorThread(); + if (creation_threads_.size() > creation_thread_original_count) { + { + std::lock_guard lock(creation_request_lock_); + creation_threads_shutdown_from_ = creation_thread_original_count; + // Assuming the queue is empty because of + // CreateQueuedPipelinesOnProcessorThread. + } + creation_request_cond_.notify_all(); + while (creation_threads_.size() > creation_thread_original_count) { + xe::threading::Wait(creation_threads_.back().get(), false); + creation_threads_.pop_back(); + } + bool await_creation_completion_event; + { + // Cleanup so additional threads can be created later again. + std::lock_guard lock(creation_request_lock_); + creation_threads_shutdown_from_ = SIZE_MAX; + // If the invocation is blocking, all the shader storage + // initialization is expected to be done before proceeding, to avoid + // latency in the command processor after the invocation. + await_creation_completion_event = + blocking && creation_threads_busy_ != 0; + if (await_creation_completion_event) { + creation_completion_event_->Reset(); + creation_completion_set_event_ = true; + } + } + if (await_creation_completion_event) { + creation_request_cond_.notify_one(); + xe::threading::Wait(creation_completion_event_.get(), false); } - } - if (await_creation_completion_event) { - creation_request_cond_.notify_one(); - xe::threading::Wait(creation_completion_event_.get(), false); } } @@ -1241,7 +1246,8 @@ bool PipelineCache::TranslateAnalyzedShader( } // Disassemble the shader for dumping. - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); if (cvars::d3d12_dxbc_disasm_dxilconv) { translation.DisassembleDxbcAndDxil(provider, cvars::d3d12_dxbc_disasm, dxbc_converter, dxc_utils, dxc_compiler); @@ -2052,8 +2058,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline( } // Create the D3D12 pipeline state object. - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); ID3D12PipelineState* state; if (FAILED(device->CreateGraphicsPipelineState(&state_desc, IID_PPV_ARGS(&state)))) { diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index f2098c9df..3c03131e3 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -869,8 +869,9 @@ TextureCache::TextureCache(D3D12CommandProcessor& command_processor, TextureCache::~TextureCache() { Shutdown(); } bool TextureCache::Initialize() { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); if (IsDrawResolutionScaled()) { // Buffers not used yet - no need aliasing barriers to change ownership of @@ -1444,7 +1445,8 @@ void TextureCache::WriteActiveTextureBindfulSRV( } } } - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); D3D12_CPU_DESCRIPTOR_HANDLE source_handle; if (descriptor_index != UINT32_MAX) { assert_not_null(texture); @@ -1622,8 +1624,7 @@ void TextureCache::WriteSampler(SamplerParameters parameters, desc.MinLOD = float(parameters.mip_min_level); // Maximum mip level is in the texture resource itself. desc.MaxLOD = FLT_MAX; - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); device->CreateSampler(&desc, handle); } @@ -1712,8 +1713,9 @@ bool TextureCache::EnsureScaledResolveMemoryCommitted( uint64_t last_scaled = uint64_t(start_unscaled + (length_unscaled - 1)) * draw_resolution_scale_area; - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); // Ensure GPU virtual memory for buffers that may be used to access the range // is allocated - buffers are created. Always creating both buffers for all @@ -1943,8 +1945,8 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2SRV( scaled_resolve_2gb_buffers_[buffer_index]; assert_not_null(buffer); ui::d3d12::util::CreateBufferTypedSRV( - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(), - handle, buffer->resource(), + command_processor_.GetD3D12Provider().GetDevice(), handle, + buffer->resource(), ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2), uint32_t(scaled_resolve_current_range_length_scaled_ >> element_size_bytes_pow2), @@ -1961,8 +1963,8 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2UAV( scaled_resolve_2gb_buffers_[buffer_index]; assert_not_null(buffer); ui::d3d12::util::CreateBufferTypedUAV( - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(), - handle, buffer->resource(), + command_processor_.GetD3D12Provider().GetDevice(), handle, + buffer->resource(), ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2), uint32_t(scaled_resolve_current_range_length_scaled_ >> element_size_bytes_pow2), @@ -2254,8 +2256,9 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) { // Untiling through a buffer instead of using unordered access because copying // is not done that often. desc.Flags = D3D12_RESOURCE_FLAG_NONE; - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); // Assuming untiling will be the next operation. D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COPY_DEST; ID3D12Resource* resource; @@ -2317,9 +2320,9 @@ bool TextureCache::LoadTextureData(Texture* texture) { return true; } - auto& command_list = command_processor_.GetDeferredCommandList(); - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + DeferredCommandList& command_list = + command_processor_.GetDeferredCommandList(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); // Get the pipeline. LoadMode load_mode = GetLoadMode(texture->key); @@ -2875,8 +2878,7 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture, host_swizzle | D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES; - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); uint32_t descriptor_index; if (bindless_resources_used_) { descriptor_index = @@ -2928,7 +2930,8 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture, D3D12_CPU_DESCRIPTOR_HANDLE TextureCache::GetTextureDescriptorCPUHandle( uint32_t descriptor_index) const { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); if (bindless_resources_used_) { return provider.OffsetViewDescriptor( command_processor_.GetViewBindlessHeapCPUStart(), descriptor_index); diff --git a/src/xenia/gpu/draw_util.cc b/src/xenia/gpu/draw_util.cc index 6cb28c9a4..83ea6601d 100644 --- a/src/xenia/gpu/draw_util.cc +++ b/src/xenia/gpu/draw_util.cc @@ -23,6 +23,7 @@ #include "xenia/gpu/texture_info.h" #include "xenia/gpu/texture_util.h" #include "xenia/gpu/xenos.h" +#include "xenia/ui/graphics_util.h" // Very prominent in 545407F2. DEFINE_bool( @@ -33,85 +34,10 @@ DEFINE_bool( "for certain games to display the scene graphics).", "GPU"); -DEFINE_bool( - present_rescale, true, - "Whether to rescale the image, instead of maintaining the original pixel " - "size, when presenting to the window. When this is disabled, other " - "positioning options are ignored.", - "GPU"); -DEFINE_bool( - present_letterbox, true, - "Maintain aspect ratio when stretching by displaying bars around the image " - "when there's no more overscan area to crop out.", - "GPU"); -// https://github.com/MonoGame/MonoGame/issues/4697#issuecomment-217779403 -// Using the value from DirectXTK (5% cropped out from each side, thus 90%), -// which is not exactly the Xbox One title-safe area, but close, and within the -// action-safe area: -// https://github.com/microsoft/DirectXTK/blob/1e80a465c6960b457ef9ab6716672c1443a45024/Src/SimpleMath.cpp#L144 -// XNA TitleSafeArea is 80%, but it's very conservative, designed for CRT, and -// is the title-safe area rather than the action-safe area. -// 90% is also exactly the fraction of 16:9 height in 16:10. -DEFINE_int32( - present_safe_area_x, 90, - "Percentage of the image width that can be kept when presenting to " - "maintain aspect ratio without letterboxing or stretching.", - "GPU"); -DEFINE_int32( - present_safe_area_y, 90, - "Percentage of the image height that can be kept when presenting to " - "maintain aspect ratio without letterboxing or stretching.", - "GPU"); - namespace xe { namespace gpu { namespace draw_util { -int32_t FloatToD3D11Fixed16p8(float f32) { - // https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#3.2.4.1%20FLOAT%20-%3E%20Fixed%20Point%20Integer - // Early exit tests. - // n == NaN || n.unbiasedExponent < -f-1 -> 0 . 0 - if (!(std::abs(f32) >= 1.0f / 512.0f)) { - return 0; - } - // n >= (2^(i-1)-2^-f) -> 2^(i-1)-1 . 2^f-1 - if (f32 >= 32768.0f - 1.0f / 256.0f) { - return (1 << 23) - 1; - } - // n <= -2^(i-1) -> -2^(i-1) . 0 - if (f32 <= -32768.0f) { - return -32768 * 256; - } - uint32_t f32_bits = *reinterpret_cast(&f32); - // Copy float32 mantissa bits [22:0] into corresponding bits [22:0] of a - // result buffer that has at least 24 bits total storage (before reaching - // rounding step further below). This includes one bit for the hidden 1. - // Set bit [23] (float32 hidden bit). - // Clear bits [31:24]. - union { - int32_t s; - uint32_t u; - } result; - result.u = (f32_bits & ((1 << 23) - 1)) | (1 << 23); - // If the sign bit is set in the float32 number (negative), then take the 2's - // component of the entire set of bits. - if ((f32_bits >> 31) != 0) { - result.s = -result.s; - } - // Final calculation: extraBits = (mantissa - f) - n.unbiasedExponent - // (guaranteed to be >= 0). - int32_t exponent = int32_t((f32_bits >> 23) & 255) - 127; - uint32_t extra_bits = uint32_t(15 - exponent); - if (extra_bits) { - // Round the 32-bit value to a decimal that is extraBits to the left of - // the LSB end, using nearest-even. - result.u += (1 << (extra_bits - 1)) - 1 + ((result.u >> extra_bits) & 1); - // Shift right by extraBits (sign extending). - result.s >>= extra_bits; - } - return result.s; -} - bool IsRasterizationPotentiallyDone(const RegisterFile& regs, bool primitive_polygonal) { // TODO(Triang3l): Investigate ModeControl::kIgnore better, with respect to @@ -746,7 +672,7 @@ bool GetResolveInfo(const RegisterFile& regs, const Memory& memory, regs.Get().pix_center ? 0.0f : 0.5f; int32_t vertices_fixed[6]; for (size_t i = 0; i < xe::countof(vertices_fixed); ++i) { - vertices_fixed[i] = FloatToD3D11Fixed16p8( + vertices_fixed[i] = ui::FloatToD3D11Fixed16p8( xenos::GpuSwap(vertices_guest[i], fetch.endian) + half_pixel_offset); } // Inclusive. @@ -1151,87 +1077,6 @@ ResolveCopyShaderIndex ResolveInfo::GetCopyShader( return shader; } -void GetPresentArea(uint32_t source_width, uint32_t source_height, - uint32_t window_width, uint32_t window_height, - int32_t& target_x_out, int32_t& target_y_out, - uint32_t& target_width_out, uint32_t& target_height_out) { - if (!cvars::present_rescale) { - target_x_out = (int32_t(window_width) - int32_t(source_width)) / 2; - target_y_out = (int32_t(window_height) - int32_t(source_height)) / 2; - target_width_out = source_width; - target_height_out = source_height; - return; - } - // Prevent division by zero. - if (!source_width || !source_height) { - target_x_out = 0; - target_y_out = 0; - target_width_out = 0; - target_height_out = 0; - return; - } - if (uint64_t(window_width) * source_height > - uint64_t(source_width) * window_height) { - // The window is wider that the source - crop along Y, then letterbox or - // stretch along X. - uint32_t present_safe_area; - if (cvars::present_safe_area_y > 0 && cvars::present_safe_area_y < 100) { - present_safe_area = uint32_t(cvars::present_safe_area_y); - } else { - present_safe_area = 100; - } - uint32_t target_height = - uint32_t(uint64_t(window_width) * source_height / source_width); - bool letterbox = false; - if (target_height * present_safe_area > window_height * 100) { - // Don't crop out more than the safe area margin - letterbox or stretch. - target_height = window_height * 100 / present_safe_area; - letterbox = true; - } - if (letterbox && cvars::present_letterbox) { - uint32_t target_width = - uint32_t(uint64_t(source_width) * window_height * 100 / - (source_height * present_safe_area)); - target_x_out = (int32_t(window_width) - int32_t(target_width)) / 2; - target_width_out = target_width; - } else { - target_x_out = 0; - target_width_out = window_width; - } - target_y_out = (int32_t(window_height) - int32_t(target_height)) / 2; - target_height_out = target_height; - } else { - // The window is taller than the source - crop along X, then letterbox or - // stretch along Y. - uint32_t present_safe_area; - if (cvars::present_safe_area_x > 0 && cvars::present_safe_area_x < 100) { - present_safe_area = uint32_t(cvars::present_safe_area_x); - } else { - present_safe_area = 100; - } - uint32_t target_width = - uint32_t(uint64_t(window_height) * source_width / source_height); - bool letterbox = false; - if (target_width * present_safe_area > window_width * 100) { - // Don't crop out more than the safe area margin - letterbox or stretch. - target_width = window_width * 100 / present_safe_area; - letterbox = true; - } - if (letterbox && cvars::present_letterbox) { - uint32_t target_height = - uint32_t(uint64_t(source_height) * window_width * 100 / - (source_width * present_safe_area)); - target_y_out = (int32_t(window_height) - int32_t(target_height)) / 2; - target_height_out = target_height; - } else { - target_y_out = 0; - target_height_out = window_height; - } - target_x_out = (int32_t(window_width) - int32_t(target_width)) / 2; - target_width_out = target_width; - } -} - } // namespace draw_util } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/draw_util.h b/src/xenia/gpu/draw_util.h index 24f58b23a..39d430676 100644 --- a/src/xenia/gpu/draw_util.h +++ b/src/xenia/gpu/draw_util.h @@ -25,15 +25,6 @@ namespace xe { namespace gpu { namespace draw_util { -// For estimating coverage extents from vertices. This may give results that are -// different than what the host GPU will actually draw (this is the reference -// conversion with 1/2 ULP accuracy, but Direct3D 11 permits 0.6 ULP tolerance -// in floating point to fixed point conversion), but is enough to tie-break -// vertices at pixel centers (due to the half-pixel offset applied to integer -// coordinates incorrectly, for instance) with some error tolerance near 0.5, -// for use with the top-left rasterization rule later. -int32_t FloatToD3D11Fixed16p8(float f32); - // Polygonal primitive types (not including points and lines) are rasterized as // triangles, have front and back faces, and also support face culling and fill // modes (polymode_front_ptype, polymode_back_ptype). Other primitive types are diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index 9f52bf046..350ea6895 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -849,7 +849,7 @@ void DxbcShaderTranslator::StartTranslation() { system_temp_aL_ = PushSystemTemp(0b1111); system_temp_loop_count_ = PushSystemTemp(0b1111); system_temp_grad_h_lod_ = PushSystemTemp(0b1111); - system_temp_grad_v_ = PushSystemTemp(0b0111); + system_temp_grad_v_vfetch_address_ = PushSystemTemp(0b1111); // Zero general-purpose registers to prevent crashes when the game // references them after only initializing them conditionally. @@ -1039,7 +1039,7 @@ void DxbcShaderTranslator::CompleteShaderCode() { // - system_temp_aL_. // - system_temp_loop_count_. // - system_temp_grad_h_lod_. - // - system_temp_grad_v_. + // - system_temp_grad_v_vfetch_address_. PopSystemTemp(6); // Write memexported data to the shared memory UAV. diff --git a/src/xenia/gpu/dxbc_shader_translator.h b/src/xenia/gpu/dxbc_shader_translator.h index 3bdde19be..0a25cef21 100644 --- a/src/xenia/gpu/dxbc_shader_translator.h +++ b/src/xenia/gpu/dxbc_shader_translator.h @@ -1104,7 +1104,9 @@ class DxbcShaderTranslator : public ShaderTranslator { uint32_t system_temp_loop_count_; // Explicitly set texture gradients and LOD. uint32_t system_temp_grad_h_lod_; - uint32_t system_temp_grad_v_; + // .w stores `base + index * stride` in bytes from the last vfetch_full as it + // may be needed by vfetch_mini. + uint32_t system_temp_grad_v_vfetch_address_; // The bool constant number containing the condition for the currently // processed exec (or the last - unless a label has reset this), or diff --git a/src/xenia/gpu/dxbc_shader_translator_fetch.cc b/src/xenia/gpu/dxbc_shader_translator_fetch.cc index 192b29a33..016841bc5 100644 --- a/src/xenia/gpu/dxbc_shader_translator_fetch.cc +++ b/src/xenia/gpu/dxbc_shader_translator_fetch.cc @@ -35,7 +35,9 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction( uint32_t used_result_components = instr.result.GetUsedResultComponents(); uint32_t needed_words = xenos::GetVertexFormatNeededWords( instr.attributes.data_format, used_result_components); - if (!needed_words) { + // If this is vfetch_full, the address may still be needed for vfetch_mini - + // don't exit before calculating the address. + if (!needed_words && instr.is_mini_fetch) { // Nothing to load - just constant 0/1 writes, or the swizzle includes only // components that don't exist in the format (writing zero instead of them). // Unpacking assumes at least some word is needed. @@ -59,47 +61,74 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction( // fetch constants on the CPU when proper bound checks are added - vfetch may // be conditional, so fetch constants may also be used conditionally. - // - Load the byte address in physical memory to system_temp_result_.w (so - // it's not overwritten by data loads until the last one). + // - Load the part of the byte address in the physical memory that is the same + // in vfetch_full and vfetch_mini to system_temp_grad_v_vfetch_address_.w + // (the index operand GPR must not be reloaded in vfetch_mini because it + // might have been overwritten previously, but that shouldn't have effect on + // vfetch_mini). - dxbc::Dest address_dest(dxbc::Dest::R(system_temp_result_, 0b1000)); - dxbc::Src address_src(dxbc::Src::R(system_temp_result_, dxbc::Src::kWWWW)); - if (instr.attributes.stride) { - // Convert the index to an integer by flooring or by rounding to the nearest - // (as floor(index + 0.5) because rounding to the nearest even makes no - // sense for addressing, both 1.5 and 2.5 would be 2). - // http://web.archive.org/web/20100302145413/http://msdn.microsoft.com:80/en-us/library/bb313960.aspx - { - bool index_operand_temp_pushed = false; - dxbc::Src index_operand( - LoadOperand(instr.operands[0], 0b0001, index_operand_temp_pushed) - .SelectFromSwizzled(0)); - if (instr.attributes.is_index_rounded) { - a_.OpAdd(address_dest, index_operand, dxbc::Src::LF(0.5f)); - a_.OpRoundNI(address_dest, address_src); - } else { - a_.OpRoundNI(address_dest, index_operand); - } - if (index_operand_temp_pushed) { - PopSystemTemp(); + dxbc::Src address_src( + dxbc::Src::R(system_temp_grad_v_vfetch_address_, dxbc::Src::kWWWW)); + if (!instr.is_mini_fetch) { + dxbc::Dest address_dest( + dxbc::Dest::R(system_temp_grad_v_vfetch_address_, 0b1000)); + if (instr.attributes.stride) { + // Convert the index to an integer by flooring or by rounding to the + // nearest (as floor(index + 0.5) because rounding to the nearest even + // makes no sense for addressing, both 1.5 and 2.5 would be 2). + { + bool index_operand_temp_pushed = false; + dxbc::Src index_operand( + LoadOperand(instr.operands[0], 0b0001, index_operand_temp_pushed) + .SelectFromSwizzled(0)); + if (instr.attributes.is_index_rounded) { + a_.OpAdd(address_dest, index_operand, dxbc::Src::LF(0.5f)); + a_.OpRoundNI(address_dest, address_src); + } else { + a_.OpRoundNI(address_dest, index_operand); + } + if (index_operand_temp_pushed) { + PopSystemTemp(); + } } + a_.OpFToI(address_dest, address_src); + // Extract the byte address from the fetch constant to + // system_temp_result_.w (which is not used yet). + a_.OpAnd(dxbc::Dest::R(system_temp_result_, 0b1000), + fetch_constant_src.SelectFromSwizzled(0), + dxbc::Src::LU(~uint32_t(3))); + // Merge the index and the base address. + a_.OpIMAd(address_dest, address_src, + dxbc::Src::LU(instr.attributes.stride * sizeof(uint32_t)), + dxbc::Src::R(system_temp_result_, dxbc::Src::kWWWW)); + } else { + // Fetching from the same location - extract the byte address of the + // beginning of the buffer. + a_.OpAnd(address_dest, fetch_constant_src.SelectFromSwizzled(0), + dxbc::Src::LU(~uint32_t(3))); } - a_.OpFToI(address_dest, address_src); - // Extract the byte address from the fetch constant to - // system_temp_result_.z. - a_.OpAnd(dxbc::Dest::R(system_temp_result_, 0b0100), - fetch_constant_src.SelectFromSwizzled(0), - dxbc::Src::LU(~uint32_t(3))); - // Merge the index and the base address. - a_.OpIMAd(address_dest, address_src, - dxbc::Src::LU(instr.attributes.stride * sizeof(uint32_t)), - dxbc::Src::R(system_temp_result_, dxbc::Src::kZZZZ)); - } else { - // Fetching from the same location - extract the byte address of the - // beginning of the buffer. - a_.OpAnd(address_dest, fetch_constant_src.SelectFromSwizzled(0), - dxbc::Src::LU(~uint32_t(3))); } + + if (!needed_words) { + // The vfetch_full address has been loaded for the subsequent vfetch_mini, + // but there's no data to load. + StoreResult(instr.result, dxbc::Src::LF(0.0f)); + return; + } + + dxbc::Dest address_temp_dest(dxbc::Dest::R(system_temp_result_, 0b1000)); + dxbc::Src address_temp_src( + dxbc::Src::R(system_temp_result_, dxbc::Src::kWWWW)); + + // - From now on, if any additional offset must be applied to the + // `base + index * stride` part of the address, it must be done by writing + // to system_temp_result_.w (address_temp_dest) instead of + // system_temp_grad_v_vfetch_address_.w (since it must stay the same for the + // vfetch_full and all its vfetch_mini invocations), and changing + // address_src to address_temp_src afterwards. system_temp_result_.w can be + // used for this purpose safely because it won't be overwritten until the + // last dword is loaded (after which the address won't be needed anymore). + // Add the word offset from the instruction (signed), plus the offset of the // first needed word within the element. uint32_t first_word_index; @@ -108,8 +137,9 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction( instr.attributes.offset + int32_t(first_word_index); if (first_word_buffer_offset) { // Add the constant word offset. - a_.OpIAdd(address_dest, address_src, + a_.OpIAdd(address_temp_dest, address_src, dxbc::Src::LI(first_word_buffer_offset * sizeof(uint32_t))); + address_src = address_temp_src; } // - Load needed words to system_temp_result_, words 0, 1, 2, 3 to X, Y, Z, W @@ -159,9 +189,10 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction( ~((uint32_t(1) << (word_index + word_count)) - uint32_t(1)); if (word_index != word_index_previous) { // Go to the word in the buffer. - a_.OpIAdd(address_dest, address_src, + a_.OpIAdd(address_temp_dest, address_src, dxbc::Src::LU((word_index - word_index_previous) * sizeof(uint32_t))); + address_src = address_temp_src; word_index_previous = word_index; } // Can ld_raw either to the first multiple components, or to any scalar @@ -592,7 +623,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( case FetchOpcode::kSetTextureGradientsVert: { bool grad_operand_temp_pushed = false; a_.OpMov( - dxbc::Dest::R(system_temp_grad_v_, 0b0111), + dxbc::Dest::R(system_temp_grad_v_vfetch_address_, 0b0111), LoadOperand(instr.operands[0], 0b0111, grad_operand_temp_pushed)); if (grad_operand_temp_pushed) { PopSystemTemp(); @@ -1521,15 +1552,15 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( // Extract gradient exponent biases from the fetch constant and merge // them with the LOD bias. a_.OpIBFE(dxbc::Dest::R(grad_h_lod_temp, 0b0011), dxbc::Src::LU(5), - dxbc::Src::LU(22, 27, 0, 0), - RequestTextureFetchConstantWord(tfetch_index, 4)); + dxbc::Src::LU(22, 27, 0, 0), + RequestTextureFetchConstantWord(tfetch_index, 4)); a_.OpIMAd(dxbc::Dest::R(grad_h_lod_temp, 0b0011), - dxbc::Src::R(grad_h_lod_temp), dxbc::Src::LI(int32_t(1) << 23), - dxbc::Src::LF(1.0f)); + dxbc::Src::R(grad_h_lod_temp), + dxbc::Src::LI(int32_t(1) << 23), dxbc::Src::LF(1.0f)); a_.OpMul(dxbc::Dest::R(grad_v_temp, 0b1000), lod_src, - dxbc::Src::R(grad_h_lod_temp, dxbc::Src::kYYYY)); + dxbc::Src::R(grad_h_lod_temp, dxbc::Src::kYYYY)); a_.OpMul(lod_dest, lod_src, - dxbc::Src::R(grad_h_lod_temp, dxbc::Src::kXXXX)); + dxbc::Src::R(grad_h_lod_temp, dxbc::Src::kXXXX)); #endif // Obtain the gradients and apply biases to them. if (instr.attributes.use_register_gradients) { @@ -1540,11 +1571,11 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( // done in getCompTexLOD, so don't do it here too. #if 0 a_.OpMul(dxbc::Dest::R(grad_v_temp, grad_mask), - dxbc::Src::R(system_temp_grad_v_), - dxbc::Src::R(grad_v_temp, dxbc::Src::kWWWW)); + dxbc::Src::R(system_temp_grad_v_vfetch_address_), + dxbc::Src::R(grad_v_temp, dxbc::Src::kWWWW)); #else a_.OpMul(dxbc::Dest::R(grad_v_temp, grad_mask), - dxbc::Src::R(system_temp_grad_v_), lod_src); + dxbc::Src::R(system_temp_grad_v_vfetch_address_), lod_src); #endif // TODO(Triang3l): Are cube map register gradients unnormalized if // the coordinates themselves are unnormalized? @@ -1586,8 +1617,8 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( // done in getCompTexLOD, so don't do it here too. #if 0 a_.OpMul(dxbc::Dest::R(grad_v_temp, grad_mask), - dxbc::Src::R(grad_v_temp), - dxbc::Src::R(grad_v_temp, dxbc::Src::kWWWW)); + dxbc::Src::R(grad_v_temp), + dxbc::Src::R(grad_v_temp, dxbc::Src::kWWWW)); #else a_.OpMul(dxbc::Dest::R(grad_v_temp, grad_mask), dxbc::Src::R(grad_v_temp), lod_src); diff --git a/src/xenia/gpu/graphics_system.cc b/src/xenia/gpu/graphics_system.cc index ec0fbaeb7..b5470fd0a 100644 --- a/src/xenia/gpu/graphics_system.cc +++ b/src/xenia/gpu/graphics_system.cc @@ -2,13 +2,19 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/gpu/graphics_system.h" +#include +#include +#include +#include +#include + #include "xenia/base/byte_stream.h" #include "xenia/base/clock.h" #include "xenia/base/logging.h" @@ -48,70 +54,40 @@ GraphicsSystem::~GraphicsSystem() = default; X_STATUS GraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) { + ui::WindowedAppContext* app_context, + [[maybe_unused]] bool is_surface_required) { memory_ = processor->memory(); processor_ = processor; kernel_state_ = kernel_state; - target_window_ = target_window; + app_context_ = app_context; - // Initialize display and rendering context. - // This must happen on the UI thread. - std::unique_ptr processor_context = nullptr; if (provider_) { - // Setup the context the command processor will do all its drawing in. - bool contexts_initialized = true; - processor_context = provider()->CreateEmulationContext(); - if (processor_context) { - if (target_window_) { - if (!target_window_->app_context().CallInUIThreadSynchronous([&]() { - // Create the context used for presentation. - assert_null(target_window->context()); - target_window_->set_context( - provider_->CreateHostContext(target_window_)); - })) { - contexts_initialized = false; - } - } + // Safe if either the UI thread call or the presenter creation fails. + if (app_context_) { + app_context_->CallInUIThreadSynchronous([this]() { + presenter_ = provider_->CreatePresenter( + [this](bool is_responsible, bool statically_from_ui_thread) { + OnHostGpuLossFromAnyThread(is_responsible); + }); + }); } else { - contexts_initialized = false; - } - if (!contexts_initialized) { - xe::FatalError( - "Unable to initialize graphics context. Xenia requires Vulkan " - "support.\n" - "\n" - "Ensure you have the latest drivers for your GPU and " - "that it supports Vulkan.\n" - "\n" - "See https://xenia.jp/faq/ for more information and a list of " - "supported GPUs."); - return X_STATUS_UNSUCCESSFUL; + // May be needed for offscreen use, such as capturing the guest output + // image. + presenter_ = provider_->CreatePresenter( + [this](bool is_responsible, bool statically_from_ui_thread) { + OnHostGpuLossFromAnyThread(is_responsible); + }); } } // Create command processor. This will spin up a thread to process all // incoming ringbuffer packets. command_processor_ = CreateCommandProcessor(); - if (!command_processor_->Initialize(std::move(processor_context))) { + if (!command_processor_->Initialize()) { XELOGE("Unable to initialize command processor"); return X_STATUS_UNSUCCESSFUL; } - if (target_window) { - command_processor_->set_swap_request_handler( - [this]() { target_window_->Invalidate(); }); - - // Watch for paint requests to do our swap. - target_window->on_painting.AddListener( - [this](xe::ui::UIEvent* e) { Swap(e); }); - - // Watch for context lost events. - target_window->on_context_lost.AddListener( - [this](xe::ui::UIEvent* e) { Reset(); }); - } else { - command_processor_->set_swap_request_handler([]() {}); - } - // Let the processor know we want register access callbacks. memory_->AddVirtualMappedRange( 0x7FC80000, 0xFFFF0000, 0x0000FFFF, this, @@ -152,6 +128,7 @@ void GraphicsSystem::Shutdown() { if (command_processor_) { EndTracing(); command_processor_->Shutdown(); + command_processor_.reset(); } if (vsync_worker_thread_) { @@ -159,13 +136,35 @@ void GraphicsSystem::Shutdown() { vsync_worker_thread_->Wait(0, 0, 0, nullptr); vsync_worker_thread_.reset(); } + + if (presenter_) { + if (app_context_) { + app_context_->CallInUIThreadSynchronous([this]() { presenter_.reset(); }); + } + // If there's no app context (thus the presenter is owned by the thread that + // initialized the GraphicsSystem) or can't be queueing UI thread calls + // anymore, shutdown anyway. + presenter_.reset(); + } + + provider_.reset(); } -void GraphicsSystem::Reset() { - // TODO(DrChat): Reset the system. - XELOGI("Context lost; Reset invoked"); - Shutdown(); - +void GraphicsSystem::OnHostGpuLossFromAnyThread( + [[maybe_unused]] bool is_responsible) { + // TODO(Triang3l): Somehow gain exclusive ownership of the Provider (may be + // used by the command processor, the presenter, and possibly anything else, + // it's considered free-threaded, except for lifetime management which will be + // involved in this case) and reset it so a new host GPU API device is + // created. Then ask the command processor to reset itself in its thread, and + // ask the UI thread to reset the Presenter (the UI thread manages its + // lifetime - but if there's no WindowedAppContext, either don't reset it as + // in this case there's no user who needs uninterrupted gameplay, or somehow + // protect it with a mutex so any thread can be considered a UI thread and + // reset). + if (host_gpu_loss_reported_.test_and_set(std::memory_order_relaxed)) { + return; + } xe::FatalError("Graphics device lost (probably due to an internal error)"); } diff --git a/src/xenia/gpu/graphics_system.h b/src/xenia/gpu/graphics_system.h index 3fd7132e1..0434a5619 100644 --- a/src/xenia/gpu/graphics_system.h +++ b/src/xenia/gpu/graphics_system.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -11,7 +11,10 @@ #define XENIA_GPU_GRAPHICS_SYSTEM_H_ #include +#include +#include #include +#include #include #include @@ -19,7 +22,9 @@ #include "xenia/gpu/register_file.h" #include "xenia/kernel/xthread.h" #include "xenia/memory.h" -#include "xenia/ui/window.h" +#include "xenia/ui/graphics_provider.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" namespace xe { @@ -41,14 +46,17 @@ class GraphicsSystem { cpu::Processor* processor() const { return processor_; } kernel::KernelState* kernel_state() const { return kernel_state_; } ui::GraphicsProvider* provider() const { return provider_.get(); } + ui::Presenter* presenter() const { return presenter_.get(); } virtual X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window); + ui::WindowedAppContext* app_context, + bool is_surface_required); virtual void Shutdown(); - virtual void Reset(); - virtual std::unique_ptr Capture() { return nullptr; } + // May be called from any thread any number of times, even during recovery + // from a device loss. + void OnHostGpuLossFromAnyThread(bool is_responsible); RegisterFile* register_file() { return ®ister_file_; } CommandProcessor* command_processor() const { @@ -91,12 +99,11 @@ class GraphicsSystem { void WriteRegister(uint32_t addr, uint32_t value); void MarkVblank(); - virtual void Swap(xe::ui::UIEvent* e) = 0; Memory* memory_ = nullptr; cpu::Processor* processor_ = nullptr; kernel::KernelState* kernel_state_ = nullptr; - ui::Window* target_window_ = nullptr; + ui::WindowedAppContext* app_context_ = nullptr; std::unique_ptr provider_; uint32_t interrupt_callback_ = 0; @@ -109,6 +116,11 @@ class GraphicsSystem { std::unique_ptr command_processor_; bool paused_ = false; + + private: + std::unique_ptr presenter_; + + std::atomic_flag host_gpu_loss_reported_; }; } // namespace gpu diff --git a/src/xenia/gpu/null/null_command_processor.cc b/src/xenia/gpu/null/null_command_processor.cc index 5d1e7a9b0..e706d5bbf 100644 --- a/src/xenia/gpu/null/null_command_processor.cc +++ b/src/xenia/gpu/null/null_command_processor.cc @@ -31,9 +31,9 @@ void NullCommandProcessor::ShutdownContext() { return CommandProcessor::ShutdownContext(); } -void NullCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, - uint32_t frontbuffer_width, - uint32_t frontbuffer_height) {} +void NullCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, + uint32_t frontbuffer_width, + uint32_t frontbuffer_height) {} Shader* NullCommandProcessor::LoadShader(xenos::ShaderType shader_type, uint32_t guest_address, diff --git a/src/xenia/gpu/null/null_command_processor.h b/src/xenia/gpu/null/null_command_processor.h index 0285b1ed2..11c829018 100644 --- a/src/xenia/gpu/null/null_command_processor.h +++ b/src/xenia/gpu/null/null_command_processor.h @@ -33,8 +33,8 @@ class NullCommandProcessor : public CommandProcessor { bool SetupContext() override; void ShutdownContext() override; - void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height) override; + void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, + uint32_t frontbuffer_height) override; Shader* LoadShader(xenos::ShaderType shader_type, uint32_t guest_address, const uint32_t* host_address, diff --git a/src/xenia/gpu/null/null_graphics_system.cc b/src/xenia/gpu/null/null_graphics_system.cc index c6df3ff09..57d5e958f 100644 --- a/src/xenia/gpu/null/null_graphics_system.cc +++ b/src/xenia/gpu/null/null_graphics_system.cc @@ -23,31 +23,20 @@ NullGraphicsSystem::~NullGraphicsSystem() {} X_STATUS NullGraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) { + ui::WindowedAppContext* app_context, + bool is_surface_required) { // This is a null graphics system, but we still setup vulkan because UI needs // it through us :| - provider_ = xe::ui::vulkan::VulkanProvider::Create(); - - return GraphicsSystem::Setup(processor, kernel_state, target_window); + provider_ = xe::ui::vulkan::VulkanProvider::Create(is_surface_required); + return GraphicsSystem::Setup(processor, kernel_state, app_context, + is_surface_required); } -void NullGraphicsSystem::Shutdown() { GraphicsSystem::Shutdown(); } - std::unique_ptr NullGraphicsSystem::CreateCommandProcessor() { return std::unique_ptr( new NullCommandProcessor(this, kernel_state_)); } -void NullGraphicsSystem::Swap(xe::ui::UIEvent* e) { - if (!command_processor_) { - return; - } - - auto& swap_state = command_processor_->swap_state(); - std::lock_guard lock(swap_state.mutex); - swap_state.pending = false; -} - } // namespace null } // namespace gpu } // namespace xe \ No newline at end of file diff --git a/src/xenia/gpu/null/null_graphics_system.h b/src/xenia/gpu/null/null_graphics_system.h index 640a0424f..d5b8d32b9 100644 --- a/src/xenia/gpu/null/null_graphics_system.h +++ b/src/xenia/gpu/null/null_graphics_system.h @@ -29,13 +29,11 @@ class NullGraphicsSystem : public GraphicsSystem { std::string name() const override { return "null"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) override; - void Shutdown() override; + ui::WindowedAppContext* app_context, + bool is_surface_required) override; private: std::unique_ptr CreateCommandProcessor() override; - - void Swap(xe::ui::UIEvent* e) override; }; } // namespace null diff --git a/src/xenia/gpu/premake5.lua b/src/xenia/gpu/premake5.lua index 15d62253d..84afcaa65 100644 --- a/src/xenia/gpu/premake5.lua +++ b/src/xenia/gpu/premake5.lua @@ -28,6 +28,7 @@ project("xenia-gpu-shader-compiler") "dxbc", "fmt", "glslang-spirv", + "snappy", "xenia-base", "xenia-gpu", "xenia-ui-vulkan", diff --git a/src/xenia/gpu/primitive_processor.cc b/src/xenia/gpu/primitive_processor.cc index 8dbe1ead3..fcb57634e 100644 --- a/src/xenia/gpu/primitive_processor.cc +++ b/src/xenia/gpu/primitive_processor.cc @@ -510,7 +510,7 @@ bool PrimitiveProcessor::Process(ProcessingResult& result_out) { SharedMemory::kBufferSize - guest_index_base < guest_index_buffer_needed_bytes) { XELOGE( - "Primitive processor: Index buffer at 0x{:8X}, 0x{:X} bytes " + "Primitive processor: Index buffer at 0x{:08X}, 0x{:X} bytes " "required, is out of the physical memory bounds", guest_index_base, guest_index_buffer_needed_bytes); assert_always(); @@ -814,7 +814,7 @@ bool PrimitiveProcessor::Process(ProcessingResult& result_out) { if (!shared_memory_.RequestRange(guest_index_base, guest_index_buffer_needed_bytes)) { XELOGE( - "PrimitiveProcessor: Failed to request index buffer 0x{:8X}, " + "PrimitiveProcessor: Failed to request index buffer 0x{:08X}, " "0x{:X} bytes needed, in the shared memory", guest_index_base, guest_index_buffer_needed_bytes); return false; diff --git a/src/xenia/gpu/shader.h b/src/xenia/gpu/shader.h index 251f73d4e..ecb45c213 100644 --- a/src/xenia/gpu/shader.h +++ b/src/xenia/gpu/shader.h @@ -435,11 +435,23 @@ struct ParsedVertexFetchInstruction { bool predicate_condition = false; // Describes how the instruction result is stored. + // Note that if the result doesn't have any components to write the fetched + // value to, the address calculation in vfetch_full must still be performed + // because such a vfetch_full may be used to setup addressing for vfetch_mini + // (wires in the color pass of 5454082B do vfetch_full to r2.000_, and then a + // true vfetch_mini). InstructionResult result; // Number of source operands. size_t operand_count = 0; // Describes each source operand. + // Note that for vfetch_mini, which inherits the operands from vfetch_full, + // the index operand register may been overwritten between the vfetch_full and + // the vfetch_mini (happens in 4D530910 for wheels), but that should have no + // effect on the index actually used for fetching. A copy of the index + // therefore must be stored by vfetch_full (the base address, stride and + // rounding may be pre-applied to it since they will be the same in the + // vfetch_full and all its vfetch_mini instructions). InstructionOperand operands[2]; struct Attributes { @@ -689,6 +701,9 @@ class Shader { // Bitmap of all bool constants read by the shader. // Each bit corresponds to a storage index [0-255]. uint32_t bool_bitmap[256 / 32]; + // Bitmap of all vertex fetch constants read by the shader. + // Each bit corresponds to a storage index [0-95]. + uint32_t vertex_fetch_bitmap[96 / 32]; // Total number of kConstantFloat registers read by the shader. uint32_t float_count; diff --git a/src/xenia/gpu/shader_translator.cc b/src/xenia/gpu/shader_translator.cc index b1d1a060e..9c1837779 100644 --- a/src/xenia/gpu/shader_translator.cc +++ b/src/xenia/gpu/shader_translator.cc @@ -282,13 +282,19 @@ void Shader::GatherVertexFetchInformation( GatherFetchResultInformation(fetch_instr.result); - // Don't bother setting up a binding for an instruction that fetches nothing. - if (!fetch_instr.result.GetUsedResultComponents()) { - return; + // Mini-fetches inherit the operands from full fetches. + if (!fetch_instr.is_mini_fetch) { + for (size_t i = 0; i < fetch_instr.operand_count; ++i) { + GatherOperandInformation(fetch_instr.operands[i]); + } } - for (size_t i = 0; i < fetch_instr.operand_count; ++i) { - GatherOperandInformation(fetch_instr.operands[i]); + // Don't bother setting up a binding for an instruction that fetches nothing. + // In case of vfetch_full, however, it may still be used to set up addressing + // for the subsequent vfetch_mini, so operand information must still be + // gathered. + if (!fetch_instr.result.GetUsedResultComponents()) { + return; } // Try to allocate an attribute on an existing binding. @@ -434,6 +440,10 @@ void Shader::GatherOperandInformation(const InstructionOperand& operand) { constant_register_map_.float_dynamic_addressing = true; } break; + case InstructionStorageSource::kVertexFetchConstant: + constant_register_map_.vertex_fetch_bitmap[operand.storage_index >> 5] |= + uint32_t(1) << (operand.storage_index & 31); + break; default: break; } @@ -876,7 +886,7 @@ bool ParseVertexFetchInstruction(const VertexFetchInstruction& op, instr.attributes.stride = full_op.stride(); instr.attributes.exp_adjust = op.exp_adjust(); instr.attributes.prefetch_count = op.prefetch_count(); - instr.attributes.is_index_rounded = op.is_index_rounded(); + instr.attributes.is_index_rounded = full_op.is_index_rounded(); instr.attributes.is_signed = op.is_signed(); instr.attributes.is_integer = !op.is_normalized(); instr.attributes.signed_rf_mode = op.signed_rf_mode(); diff --git a/src/xenia/gpu/shader_translator_disasm.cc b/src/xenia/gpu/shader_translator_disasm.cc index cf7e94d52..8dd72413a 100644 --- a/src/xenia/gpu/shader_translator_disasm.cc +++ b/src/xenia/gpu/shader_translator_disasm.cc @@ -328,13 +328,12 @@ void ParsedVertexFetchInstruction::Disassemble(StringBuffer* out) const { if (!is_mini_fetch) { out->Append(", "); DisassembleSourceOperand(operands[0], out); - out->Append(", "); - out->AppendFormat("vf{}", 95 - operands[1].storage_index); + out->AppendFormat(", vf{}", 95 - operands[1].storage_index); + if (attributes.is_index_rounded) { + out->Append(", RoundIndex=true"); + } } - if (attributes.is_index_rounded) { - out->Append(", RoundIndex=true"); - } if (attributes.exp_adjust) { out->AppendFormat(", ExpAdjust={}", attributes.exp_adjust); } diff --git a/src/xenia/gpu/shaders/apply_gamma_pwl.cs.hlsl b/src/xenia/gpu/shaders/apply_gamma_pwl.cs.hlsl new file mode 100644 index 000000000..8ba176f73 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_pwl.cs.hlsl @@ -0,0 +1,2 @@ +float XeApplyGammaGetAlpha(float3 color) { return 1.0f; } +#include "apply_gamma_pwl.hlsli" diff --git a/src/xenia/gpu/shaders/apply_gamma_pwl.hlsli b/src/xenia/gpu/shaders/apply_gamma_pwl.hlsli new file mode 100644 index 000000000..a77c85460 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_pwl.hlsli @@ -0,0 +1,41 @@ +// float XeApplyGammaGetAlpha(float3 color) needs to be specified externally. + +cbuffer XeApplyGammaRampConstants : register(b0) { + uint2 xe_apply_gamma_size; +}; +RWTexture2D xe_apply_gamma_dest : register(u0); +Texture2D xe_apply_gamma_source : register(t0); +Buffer xe_apply_gamma_ramp : register(t1); + +float XeApplyPWLGamma(uint input, uint component) { + // TODO(Triang3l): If this is ever used for gamma other than 128 entries for a + // 10bpc front buffer, handle the increment from DC_LUTA/B_CONTROL. Currently + // assuming it's 2^3 = 8, or 1024 / 128. + // output = base + (multiplier * delta) / increment + // https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf + // The lower 6 bits of the base and the delta are 0 (though enforcing that in + // the shader is not necessary). + // The `(multiplier * delta) / increment` part may result in a nonzero value + // in the lower 6 bits of the result, however, so doing `* (1.0f / 64.0f)` + // instead of `>> 6` to preserve them (if the render target is 16bpc rather + // than 10bpc, for instance). + uint2 ramp_value = xe_apply_gamma_ramp[(input >> 3u) * 3u + component]; + return saturate((float(ramp_value.x) + + float((input & 7u) * ramp_value.y) * (1.0f / 8.0f)) * + (1.0f / (64.0f * 1023.0f))); +} + +[numthreads(8, 8, 1)] +void main(uint3 xe_thread_id : SV_DispatchThreadID) { + [branch] if (any(xe_thread_id.xy >= xe_apply_gamma_size)) { + return; + } + // UNORM conversion according to the Direct3D 10+ rules. + uint3 input = uint3(xe_apply_gamma_source[xe_thread_id.xy] * 1023.0f + 0.5f); + // The ramp is BGR, not RGB. + float3 output = float3(XeApplyPWLGamma(input.r, 2u), + XeApplyPWLGamma(input.g, 1u), + XeApplyPWLGamma(input.b, 0u)); + xe_apply_gamma_dest[xe_thread_id.xy] = + float4(output, XeApplyGammaGetAlpha(output)); +} diff --git a/src/xenia/gpu/shaders/apply_gamma_pwl_fxaa_luma.cs.hlsl b/src/xenia/gpu/shaders/apply_gamma_pwl_fxaa_luma.cs.hlsl new file mode 100644 index 000000000..3a6bb4f9b --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_pwl_fxaa_luma.cs.hlsl @@ -0,0 +1,5 @@ +// Perceptual luminance for FXAA. +float XeApplyGammaGetAlpha(float3 color) { + return dot(color, float3(0.299, 0.587, 0.114)); +} +#include "apply_gamma_pwl.hlsli" diff --git a/src/xenia/gpu/shaders/apply_gamma_table.cs.hlsl b/src/xenia/gpu/shaders/apply_gamma_table.cs.hlsl new file mode 100644 index 000000000..94b43ddd8 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_table.cs.hlsl @@ -0,0 +1,2 @@ +float XeApplyGammaGetAlpha(float3 color) { return 1.0f; } +#include "apply_gamma_table.hlsli" diff --git a/src/xenia/gpu/shaders/apply_gamma_table.hlsli b/src/xenia/gpu/shaders/apply_gamma_table.hlsli new file mode 100644 index 000000000..7f43a9567 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_table.hlsli @@ -0,0 +1,23 @@ +// float XeApplyGammaGetAlpha(float3 color) needs to be specified externally. + +cbuffer XeApplyGammaRampConstants : register(b0) { + uint2 xe_apply_gamma_size; +}; +RWTexture2D xe_apply_gamma_dest : register(u0); +Texture2D xe_apply_gamma_source : register(t0); +Buffer xe_apply_gamma_ramp : register(t1); + +[numthreads(8, 8, 1)] +void main(uint3 xe_thread_id : SV_DispatchThreadID) { + [branch] if (any(xe_thread_id.xy >= xe_apply_gamma_size)) { + return; + } + // UNORM conversion according to the Direct3D 10+ rules. + uint3 input = uint3(xe_apply_gamma_source[xe_thread_id.xy] * 255.0f + 0.5f); + // The ramp is BGR, not RGB. + float3 output = float3(xe_apply_gamma_ramp[input.r].b, + xe_apply_gamma_ramp[input.g].g, + xe_apply_gamma_ramp[input.b].r); + xe_apply_gamma_dest[xe_thread_id.xy] = + float4(output, XeApplyGammaGetAlpha(output)); +} diff --git a/src/xenia/gpu/shaders/apply_gamma_table_fxaa_luma.cs.hlsl b/src/xenia/gpu/shaders/apply_gamma_table_fxaa_luma.cs.hlsl new file mode 100644 index 000000000..16b2593f2 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_table_fxaa_luma.cs.hlsl @@ -0,0 +1,5 @@ +// Perceptual luminance for FXAA. +float XeApplyGammaGetAlpha(float3 color) { + return dot(color, float3(0.299, 0.587, 0.114)); +} +#include "apply_gamma_table.hlsli" diff --git a/src/xenia/gpu/shaders/bytecode/.clang-format b/src/xenia/gpu/shaders/bytecode/.clang-format index e3845288a..9d159247d 100644 --- a/src/xenia/gpu/shaders/bytecode/.clang-format +++ b/src/xenia/gpu/shaders/bytecode/.clang-format @@ -1 +1,2 @@ DisableFormat: true +SortIncludes: false diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h index ecae25810..1ff1d3d38 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h @@ -84,10 +84,10 @@ ret const BYTE adaptive_quad_hs[] = { - 68, 88, 66, 67, 94, 229, - 104, 122, 195, 92, 144, 36, - 252, 149, 235, 210, 131, 205, - 139, 42, 1, 0, 0, 0, + 68, 88, 66, 67, 91, 114, + 196, 93, 35, 195, 210, 49, + 154, 70, 168, 244, 8, 132, + 25, 246, 1, 0, 0, 0, 176, 4, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 164, 0, 0, 0, 220, 0, @@ -98,7 +98,7 @@ const BYTE adaptive_quad_hs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 60, 0, + 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h index 682d79b83..4d9950a38 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h @@ -73,10 +73,10 @@ ret const BYTE adaptive_triangle_hs[] = { - 68, 88, 66, 67, 86, 168, - 189, 119, 111, 17, 238, 147, - 225, 129, 174, 39, 170, 24, - 24, 225, 1, 0, 0, 0, + 68, 88, 66, 67, 10, 165, + 117, 176, 19, 12, 130, 108, + 171, 104, 195, 161, 52, 251, + 99, 193, 1, 0, 0, 0, 224, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 164, 0, 0, 0, 220, 0, @@ -87,7 +87,7 @@ const BYTE adaptive_triangle_hs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 60, 0, + 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h new file mode 100644 index 000000000..727d15384 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h @@ -0,0 +1,409 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_apply_gamma_source texture float3 2d T0 t0 1 +// xe_apply_gamma_ramp texture uint2 buf T1 t1 1 +// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_resource_buffer (uint,uint,uint,uint) T1[1:1], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 3 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +mov r0.xy, vThreadID.xyxx +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mad r0.xyz, r0.xyzx, l(1023.000000, 1023.000000, 1023.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +ftou r0.xyz, r0.xyzx +ushr r1.xyz, r0.xyzx, l(3, 3, 3, 0) +imul null, r0.w, r1.z, l(3) +imad r1.xy, r1.xyxx, l(3, 3, 0, 0), l(2, 1, 0, 0) +ld r1.xz, r1.xxxx, T1[1].xzyw +utof r1.x, r1.x +and r0.xyz, r0.xyzx, l(7, 7, 7, 0) +imul null, r0.x, r1.z, r0.x +utof r0.x, r0.x +mad r0.x, r0.x, l(0.125000), r1.x +mul r0.x, r0.x, l(0.000015) +min r2.x, r0.x, l(1.000000) +ld r1.xy, r1.yyyy, T1[1].xyzw +utof r0.x, r1.x +imul null, r0.y, r0.y, r1.y +utof r0.y, r0.y +mad r0.x, r0.y, l(0.125000), r0.x +mul r0.x, r0.x, l(0.000015) +min r2.y, r0.x, l(1.000000) +ld r0.xy, r0.wwww, T1[1].xyzw +imul null, r0.y, r0.y, r0.z +utof r0.xy, r0.xyxx +mad r0.x, r0.y, l(0.125000), r0.x +mul r0.x, r0.x, l(0.000015) +min r2.z, r0.x, l(1.000000) +mov r2.w, l(1.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r2.xyzw +ret +// Approximately 37 instruction slots used +#endif + +const BYTE apply_gamma_pwl_cs[] = +{ + 68, 88, 66, 67, 180, 180, + 222, 28, 4, 138, 188, 113, + 52, 97, 214, 88, 116, 106, + 105, 240, 1, 0, 0, 0, + 128, 7, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 24, 2, 0, 0, 40, 2, + 0, 0, 56, 2, 0, 0, + 228, 6, 0, 0, 82, 68, + 69, 70, 220, 1, 0, 0, + 1, 0, 0, 0, 52, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 180, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 115, 111, 117, 114, 99, + 101, 0, 120, 101, 95, 97, + 112, 112, 108, 121, 95, 103, + 97, 109, 109, 97, 95, 114, + 97, 109, 112, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 100, 101, 115, 116, 0, + 88, 101, 65, 112, 112, 108, + 121, 71, 97, 109, 109, 97, + 82, 97, 109, 112, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 26, 1, 0, 0, + 1, 0, 0, 0, 76, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 144, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 97, 112, 112, + 108, 121, 95, 103, 97, 109, + 109, 97, 95, 115, 105, 122, + 101, 0, 117, 105, 110, 116, + 50, 0, 171, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 164, 4, 0, 0, + 81, 0, 5, 0, 41, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 88, 8, 0, 7, + 70, 126, 48, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 68, 68, + 0, 0, 0, 0, 0, 0, + 156, 24, 0, 7, 70, 238, + 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 95, 0, + 0, 2, 50, 0, 2, 0, + 104, 0, 0, 2, 3, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 2, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 4, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 192, + 127, 68, 0, 192, 127, 68, + 0, 192, 127, 68, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 28, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 10, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 35, 0, 0, 15, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 82, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 134, 125, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 7, 0, + 0, 0, 7, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 18, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 62, 10, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 32, 128, 55, 51, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 45, 0, 0, 8, + 50, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 1, 0, 0, 0, 70, 126, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 86, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 62, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 32, + 128, 55, 51, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 45, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 62, 10, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 32, 128, 55, 51, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 54, 0, 0, 5, + 130, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 164, 0, + 0, 7, 242, 224, 33, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 5, 2, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 37, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 10, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h new file mode 100644 index 000000000..ed86b4d4a --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h @@ -0,0 +1,413 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_apply_gamma_source texture float3 2d T0 t0 1 +// xe_apply_gamma_ramp texture uint2 buf T1 t1 1 +// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_resource_buffer (uint,uint,uint,uint) T1[1:1], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 3 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +mov r0.xy, vThreadID.xyxx +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mad r0.xyz, r0.xyzx, l(1023.000000, 1023.000000, 1023.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +ftou r0.xyz, r0.xyzx +ushr r1.xyz, r0.xyzx, l(3, 3, 3, 0) +imul null, r0.w, r1.z, l(3) +imad r1.xy, r1.xyxx, l(3, 3, 0, 0), l(2, 1, 0, 0) +ld r1.xz, r1.xxxx, T1[1].xzyw +utof r1.x, r1.x +and r0.xyz, r0.xyzx, l(7, 7, 7, 0) +imul null, r0.x, r1.z, r0.x +utof r0.x, r0.x +mad r0.x, r0.x, l(0.125000), r1.x +mul r0.x, r0.x, l(0.000015) +min r2.x, r0.x, l(1.000000) +ld r1.xy, r1.yyyy, T1[1].xyzw +utof r0.x, r1.x +imul null, r0.y, r0.y, r1.y +utof r0.y, r0.y +mad r0.x, r0.y, l(0.125000), r0.x +mul r0.x, r0.x, l(0.000015) +min r2.y, r0.x, l(1.000000) +ld r0.xy, r0.wwww, T1[1].xyzw +imul null, r0.y, r0.y, r0.z +utof r0.xy, r0.xyxx +mad r0.x, r0.y, l(0.125000), r0.x +mul r0.x, r0.x, l(0.000015) +min r2.z, r0.x, l(1.000000) +dp3 r2.w, r2.xyzx, l(0.299000, 0.587000, 0.114000, 0.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r2.xyzw +ret +// Approximately 37 instruction slots used +#endif + +const BYTE apply_gamma_pwl_fxaa_luma_cs[] = +{ + 68, 88, 66, 67, 165, 122, + 242, 36, 160, 218, 193, 67, + 37, 43, 138, 45, 109, 219, + 226, 109, 1, 0, 0, 0, + 148, 7, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 24, 2, 0, 0, 40, 2, + 0, 0, 56, 2, 0, 0, + 248, 6, 0, 0, 82, 68, + 69, 70, 220, 1, 0, 0, + 1, 0, 0, 0, 52, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 180, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 115, 111, 117, 114, 99, + 101, 0, 120, 101, 95, 97, + 112, 112, 108, 121, 95, 103, + 97, 109, 109, 97, 95, 114, + 97, 109, 112, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 100, 101, 115, 116, 0, + 88, 101, 65, 112, 112, 108, + 121, 71, 97, 109, 109, 97, + 82, 97, 109, 112, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 26, 1, 0, 0, + 1, 0, 0, 0, 76, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 144, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 97, 112, 112, + 108, 121, 95, 103, 97, 109, + 109, 97, 95, 115, 105, 122, + 101, 0, 117, 105, 110, 116, + 50, 0, 171, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 184, 4, 0, 0, + 81, 0, 5, 0, 46, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 88, 8, 0, 7, + 70, 126, 48, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 68, 68, + 0, 0, 0, 0, 0, 0, + 156, 24, 0, 7, 70, 238, + 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 95, 0, + 0, 2, 50, 0, 2, 0, + 104, 0, 0, 2, 3, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 2, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 4, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 192, + 127, 68, 0, 192, 127, 68, + 0, 192, 127, 68, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 28, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 10, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 35, 0, 0, 15, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 82, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 134, 125, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 7, 0, + 0, 0, 7, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 18, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 62, 10, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 32, 128, 55, 51, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 45, 0, 0, 8, + 50, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 1, 0, 0, 0, 70, 126, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 86, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 62, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 32, + 128, 55, 51, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 45, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 62, 10, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 32, 128, 55, 51, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 16, 0, 0, 10, + 130, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 135, 22, 153, 62, + 162, 69, 22, 63, 213, 120, + 233, 61, 0, 0, 0, 0, + 164, 0, 0, 7, 242, 224, + 33, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 5, + 2, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 37, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 11, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h new file mode 100644 index 000000000..a890e8f48 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h @@ -0,0 +1,281 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_apply_gamma_source texture float3 2d T0 t0 1 +// xe_apply_gamma_ramp texture float3 buf T1 t1 1 +// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_resource_buffer (float,float,float,float) T1[1:1], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 2 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +mov r0.xy, vThreadID.xyxx +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mad r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +ftou r0.xyz, r0.xyzx +ld r1.x, r0.xxxx, T1[1].zxyw +ld r1.y, r0.yyyy, T1[1].xyzw +ld r1.z, r0.zzzz, T1[1].yzxw +mov r1.w, l(1.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw +ret +// Approximately 16 instruction slots used +#endif + +const BYTE apply_gamma_table_cs[] = +{ + 68, 88, 66, 67, 20, 63, + 31, 100, 63, 232, 227, 64, + 21, 8, 34, 27, 205, 36, + 202, 71, 1, 0, 0, 0, + 252, 4, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 24, 2, 0, 0, 40, 2, + 0, 0, 56, 2, 0, 0, + 96, 4, 0, 0, 82, 68, + 69, 70, 220, 1, 0, 0, + 1, 0, 0, 0, 52, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 180, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 115, 111, 117, 114, 99, + 101, 0, 120, 101, 95, 97, + 112, 112, 108, 121, 95, 103, + 97, 109, 109, 97, 95, 114, + 97, 109, 112, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 100, 101, 115, 116, 0, + 88, 101, 65, 112, 112, 108, + 121, 71, 97, 109, 109, 97, + 82, 97, 109, 112, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 26, 1, 0, 0, + 1, 0, 0, 0, 76, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 144, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 97, 112, 112, + 108, 121, 95, 103, 97, 109, + 109, 97, 95, 115, 105, 122, + 101, 0, 117, 105, 110, 116, + 50, 0, 171, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 32, 2, 0, 0, + 81, 0, 5, 0, 136, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 88, 8, 0, 7, + 70, 126, 48, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, + 156, 24, 0, 7, 70, 238, + 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 95, 0, + 0, 2, 50, 0, 2, 0, + 104, 0, 0, 2, 2, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 2, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 4, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 127, 67, 0, 0, 127, 67, + 0, 0, 127, 67, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 28, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 38, 125, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 45, 0, 0, 8, + 34, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 45, 0, + 0, 8, 66, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 150, 124, 32, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 164, 0, 0, 7, + 242, 224, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 5, 2, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 16, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h new file mode 100644 index 000000000..4373d8498 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h @@ -0,0 +1,284 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_apply_gamma_source texture float3 2d T0 t0 1 +// xe_apply_gamma_ramp texture float3 buf T1 t1 1 +// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_resource_buffer (float,float,float,float) T1[1:1], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 2 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +mov r0.xy, vThreadID.xyxx +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mad r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +ftou r0.xyz, r0.xyzx +ld r1.x, r0.xxxx, T1[1].zxyw +ld r1.y, r0.yyyy, T1[1].xyzw +ld r1.z, r0.zzzz, T1[1].yzxw +dp3 r1.w, r1.xyzx, l(0.299000, 0.587000, 0.114000, 0.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw +ret +// Approximately 16 instruction slots used +#endif + +const BYTE apply_gamma_table_fxaa_luma_cs[] = +{ + 68, 88, 66, 67, 148, 92, + 39, 196, 202, 33, 41, 82, + 77, 137, 192, 188, 150, 218, + 30, 64, 1, 0, 0, 0, + 16, 5, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 24, 2, 0, 0, 40, 2, + 0, 0, 56, 2, 0, 0, + 116, 4, 0, 0, 82, 68, + 69, 70, 220, 1, 0, 0, + 1, 0, 0, 0, 52, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 180, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 115, 111, 117, 114, 99, + 101, 0, 120, 101, 95, 97, + 112, 112, 108, 121, 95, 103, + 97, 109, 109, 97, 95, 114, + 97, 109, 112, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 100, 101, 115, 116, 0, + 88, 101, 65, 112, 112, 108, + 121, 71, 97, 109, 109, 97, + 82, 97, 109, 112, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 26, 1, 0, 0, + 1, 0, 0, 0, 76, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 144, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 97, 112, 112, + 108, 121, 95, 103, 97, 109, + 109, 97, 95, 115, 105, 122, + 101, 0, 117, 105, 110, 116, + 50, 0, 171, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 52, 2, 0, 0, + 81, 0, 5, 0, 141, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 88, 8, 0, 7, + 70, 126, 48, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, + 156, 24, 0, 7, 70, 238, + 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 95, 0, + 0, 2, 50, 0, 2, 0, + 104, 0, 0, 2, 2, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 2, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 4, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 127, 67, 0, 0, 127, 67, + 0, 0, 127, 67, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 28, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 38, 125, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 45, 0, 0, 8, + 34, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 45, 0, + 0, 8, 66, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 150, 124, 32, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 16, 0, 0, 10, 130, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 135, 22, 153, 62, 162, 69, + 22, 63, 213, 120, 233, 61, + 0, 0, 0, 0, 164, 0, + 0, 7, 242, 224, 33, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 5, 2, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/clear_uint2_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/clear_uint2_ps.h index 12d936ccf..8bf1a7d63 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/clear_uint2_ps.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/clear_uint2_ps.h @@ -44,10 +44,10 @@ ret const BYTE clear_uint2_ps[] = { - 68, 88, 66, 67, 37, 23, - 17, 1, 102, 148, 181, 42, - 241, 102, 112, 167, 142, 147, - 73, 7, 1, 0, 0, 0, + 68, 88, 66, 67, 90, 79, + 67, 15, 17, 175, 210, 170, + 189, 222, 209, 228, 62, 31, + 153, 246, 1, 0, 0, 0, 148, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 88, 1, 0, 0, 104, 1, @@ -57,7 +57,7 @@ const BYTE clear_uint2_ps[] = 1, 0, 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, + 255, 255, 0, 5, 0, 0, 244, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h index cba1c29ab..9969afd5f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h @@ -121,10 +121,10 @@ ret const BYTE continuous_quad_hs[] = { - 68, 88, 66, 67, 109, 174, - 137, 67, 82, 213, 246, 48, - 97, 232, 232, 104, 109, 96, - 97, 35, 1, 0, 0, 0, + 68, 88, 66, 67, 38, 148, + 187, 235, 226, 45, 172, 116, + 78, 244, 151, 91, 91, 131, + 203, 9, 1, 0, 0, 0, 240, 13, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 188, 10, 0, 0, 240, 10, @@ -135,7 +135,7 @@ const BYTE continuous_quad_hs[] = 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 82, 10, + 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h index afd8a3347..7ebd3f557 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h @@ -112,10 +112,10 @@ ret const BYTE continuous_triangle_hs[] = { - 68, 88, 66, 67, 150, 55, - 56, 98, 126, 111, 114, 179, - 197, 7, 10, 15, 70, 32, - 249, 93, 1, 0, 0, 0, + 68, 88, 66, 67, 73, 225, + 250, 199, 94, 238, 81, 135, + 38, 37, 240, 107, 243, 39, + 228, 138, 1, 0, 0, 0, 96, 13, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 188, 10, 0, 0, 240, 10, @@ -126,7 +126,7 @@ const BYTE continuous_triangle_hs[] = 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 82, 10, + 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h index 53a0af447..3fb7e283f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h @@ -121,10 +121,10 @@ ret const BYTE discrete_quad_hs[] = { - 68, 88, 66, 67, 174, 141, - 75, 94, 70, 108, 133, 212, - 18, 161, 84, 115, 238, 199, - 1, 25, 1, 0, 0, 0, + 68, 88, 66, 67, 30, 187, + 71, 171, 142, 3, 72, 194, + 131, 236, 131, 25, 126, 147, + 165, 207, 1, 0, 0, 0, 240, 13, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 188, 10, 0, 0, 240, 10, @@ -135,7 +135,7 @@ const BYTE discrete_quad_hs[] = 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 82, 10, + 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h index d5855480a..4d4118deb 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h @@ -112,10 +112,10 @@ ret const BYTE discrete_triangle_hs[] = { - 68, 88, 66, 67, 100, 231, - 203, 227, 24, 0, 204, 209, - 145, 54, 166, 75, 102, 255, - 190, 98, 1, 0, 0, 0, + 68, 88, 66, 67, 59, 166, + 23, 194, 170, 244, 84, 16, + 156, 139, 156, 141, 147, 143, + 102, 19, 1, 0, 0, 0, 96, 13, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 188, 10, 0, 0, 240, 10, @@ -126,7 +126,7 @@ const BYTE discrete_triangle_hs[] = 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 82, 10, + 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_round_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_round_ps.h index ca93f0d29..8a82eb0e7 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_round_ps.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_round_ps.h @@ -76,10 +76,10 @@ ret const BYTE float24_round_ps[] = { - 68, 88, 66, 67, 23, 65, - 158, 4, 125, 87, 131, 240, - 183, 241, 233, 246, 170, 100, - 46, 3, 1, 0, 0, 0, + 68, 88, 66, 67, 229, 54, + 46, 1, 194, 31, 164, 202, + 193, 71, 175, 129, 44, 52, + 218, 154, 1, 0, 0, 0, 8, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 120, 2, @@ -89,7 +89,7 @@ const BYTE float24_round_ps[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, + 255, 255, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_truncate_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_truncate_ps.h index 1111cd47f..91eb48136 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_truncate_ps.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_truncate_ps.h @@ -58,10 +58,10 @@ ret const BYTE float24_truncate_ps[] = { - 68, 88, 66, 67, 73, 81, - 190, 30, 130, 230, 10, 4, - 35, 6, 194, 2, 204, 207, - 200, 64, 1, 0, 0, 0, + 68, 88, 66, 67, 234, 72, + 187, 196, 185, 155, 10, 179, + 119, 204, 17, 88, 131, 142, + 107, 205, 1, 0, 0, 0, 140, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 120, 2, @@ -71,7 +71,7 @@ const BYTE float24_truncate_ps[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, + 255, 255, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h deleted file mode 100644 index c14aebabf..000000000 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h +++ /dev/null @@ -1,166 +0,0 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 10.1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_VertexID 0 x 0 VERTID uint x -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// TEXCOORD 0 xy 0 NONE float xy -// SV_Position 0 xyzw 1 POS float xyzw -// -vs_5_1 -dcl_globalFlags refactoringAllowed -dcl_input_sgv v0.x, vertex_id -dcl_output o0.xy -dcl_output_siv o1.xyzw, position -dcl_temps 1 -ishl r0.y, v0.x, l(1) -mov r0.x, v0.x -and r0.xy, r0.xyxx, l(2, 2, 0, 0) -utof r0.xy, r0.xyxx -mad o1.xy, r0.xyxx, l(2.000000, -2.000000, 0.000000, 0.000000), l(-1.000000, 1.000000, 0.000000, 0.000000) -mov o1.zw, l(0,0,0,1.000000) -mov o0.xy, r0.xyxx -ret -// Approximately 8 instruction slots used -#endif - -const BYTE fullscreen_tc_vs[] = -{ - 68, 88, 66, 67, 194, 19, - 91, 0, 93, 21, 209, 27, - 252, 153, 187, 171, 84, 80, - 251, 138, 1, 0, 0, 0, - 240, 2, 0, 0, 5, 0, - 0, 0, 52, 0, 0, 0, - 160, 0, 0, 0, 212, 0, - 0, 0, 44, 1, 0, 0, - 84, 2, 0, 0, 82, 68, - 69, 70, 100, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, - 60, 0, 0, 0, 19, 19, - 68, 37, 60, 0, 0, 0, - 24, 0, 0, 0, 40, 0, - 0, 0, 40, 0, 0, 0, - 36, 0, 0, 0, 12, 0, - 0, 0, 0, 0, 0, 0, - 77, 105, 99, 114, 111, 115, - 111, 102, 116, 32, 40, 82, - 41, 32, 72, 76, 83, 76, - 32, 83, 104, 97, 100, 101, - 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 73, 83, - 71, 78, 44, 0, 0, 0, - 1, 0, 0, 0, 8, 0, - 0, 0, 32, 0, 0, 0, - 0, 0, 0, 0, 6, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 1, - 0, 0, 83, 86, 95, 86, - 101, 114, 116, 101, 120, 73, - 68, 0, 79, 83, 71, 78, - 80, 0, 0, 0, 2, 0, - 0, 0, 8, 0, 0, 0, - 56, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 3, 12, 0, 0, - 65, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 3, 0, 0, 0, 1, 0, - 0, 0, 15, 0, 0, 0, - 84, 69, 88, 67, 79, 79, - 82, 68, 0, 83, 86, 95, - 80, 111, 115, 105, 116, 105, - 111, 110, 0, 171, 171, 171, - 83, 72, 69, 88, 32, 1, - 0, 0, 81, 0, 1, 0, - 72, 0, 0, 0, 106, 8, - 0, 1, 96, 0, 0, 4, - 18, 16, 16, 0, 0, 0, - 0, 0, 6, 0, 0, 0, - 101, 0, 0, 3, 50, 32, - 16, 0, 0, 0, 0, 0, - 103, 0, 0, 4, 242, 32, - 16, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 104, 0, - 0, 2, 1, 0, 0, 0, - 41, 0, 0, 7, 34, 0, - 16, 0, 0, 0, 0, 0, - 10, 16, 16, 0, 0, 0, - 0, 0, 1, 64, 0, 0, - 1, 0, 0, 0, 54, 0, - 0, 5, 18, 0, 16, 0, - 0, 0, 0, 0, 10, 16, - 16, 0, 0, 0, 0, 0, - 1, 0, 0, 10, 50, 0, - 16, 0, 0, 0, 0, 0, - 70, 0, 16, 0, 0, 0, - 0, 0, 2, 64, 0, 0, - 2, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 86, 0, - 0, 5, 50, 0, 16, 0, - 0, 0, 0, 0, 70, 0, - 16, 0, 0, 0, 0, 0, - 50, 0, 0, 15, 50, 32, - 16, 0, 1, 0, 0, 0, - 70, 0, 16, 0, 0, 0, - 0, 0, 2, 64, 0, 0, - 0, 0, 0, 64, 0, 0, - 0, 192, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 64, - 0, 0, 0, 0, 128, 191, - 0, 0, 128, 63, 0, 0, - 0, 0, 0, 0, 0, 0, - 54, 0, 0, 8, 194, 32, - 16, 0, 1, 0, 0, 0, - 2, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 128, 63, 54, 0, 0, 5, - 50, 32, 16, 0, 0, 0, - 0, 0, 70, 0, 16, 0, - 0, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 148, 0, 0, 0, 8, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0 -}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h index f12247ce4..5a388c0a8 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h @@ -34,10 +34,10 @@ ret const BYTE fullscreen_vs[] = { - 68, 88, 66, 67, 11, 43, - 171, 43, 233, 188, 20, 107, - 115, 148, 0, 215, 116, 165, - 194, 26, 1, 0, 0, 0, + 68, 88, 66, 67, 111, 71, + 234, 43, 238, 70, 168, 114, + 17, 145, 139, 145, 152, 124, + 190, 180, 1, 0, 0, 0, 172, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 212, 0, @@ -47,7 +47,7 @@ const BYTE fullscreen_vs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, + 254, 255, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h new file mode 100644 index 000000000..8ca505c28 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h @@ -0,0 +1,1270 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_fxaa_size; // Offset: 0 Size: 8 +// float2 xe_fxaa_size_inv; // Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_sampler_linear_clamp sampler NA NA S0 s0 1 +// xe_fxaa_source texture float4 2d T0 t0 1 +// xe_fxaa_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_sampler S0[0:0], mode_default, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 7 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +utof r0.xy, vThreadID.xyxx +add r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000) +mul r0.zw, r0.xxxy, CB0[0][0].zzzw +sample_l r1.xyzw, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +gather4 r2.xyz, r0.zwzz, T0[0].xyzw, S0[0].w +gather4_aoffimmi(-1,-1,0) r3.xyz, r0.zwzz, T0[0].zxwy, S0[0].w +max r2.w, r1.w, r2.x +min r3.w, r1.w, r2.x +max r2.w, r2.w, r2.z +min r3.w, r2.z, r3.w +max r4.x, r3.y, r3.x +min r4.y, r3.y, r3.x +max r2.w, r2.w, r4.x +min r3.w, r3.w, r4.y +mul r4.x, r2.w, l(0.166000) +add r2.w, r2.w, -r3.w +max r3.w, r4.x, l(0.083300) +lt r3.w, r2.w, r3.w +if_z r3.w +endif +if_z r3.w + sample_l_aoffimmi(1,-1,0) r3.w, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) + sample_l_aoffimmi(-1,1,0) r4.x, r0.zwzz, T0[0].wxyz, S0[0], l(0.000000) + add r4.yz, r2.xxzx, r3.xxyx + div r2.w, l(1.000000, 1.000000, 1.000000, 1.000000), r2.w + add r4.w, r4.z, r4.y + mad r4.yz, r1.wwww, l(0.000000, -2.000000, -2.000000, 0.000000), r4.yyzy + add r5.x, r2.y, r3.w + add r3.w, r3.w, r3.z + mad r5.y, r2.z, l(-2.000000), r5.x + mad r3.w, r3.x, l(-2.000000), r3.w + add r3.z, r3.z, r4.x + add r2.y, r2.y, r4.x + mad r4.x, |r4.y|, l(2.000000), |r5.y| + mad r3.w, |r4.z|, l(2.000000), |r3.w| + mad r4.y, r3.y, l(-2.000000), r3.z + mad r2.y, r2.x, l(-2.000000), r2.y + add r4.x, r4.x, |r4.y| + add r2.y, r3.w, |r2.y| + add r3.z, r5.x, r3.z + ge r2.y, r4.x, r2.y + mad r3.z, r4.w, l(2.000000), r3.z + if_z r2.y + mov r3.x, r3.y + mov r2.x, r2.z + endif + if_nz r2.y + mov r2.z, CB0[0][0].w + else + mov r2.z, CB0[0][0].z + endif + mad r3.y, r3.z, l(0.083333), -r1.w + add r3.z, -r1.w, r3.x + add r3.w, -r1.w, r2.x + ge r4.x, |r3.z|, |r3.w| + max r3.z, |r3.w|, |r3.z| + if_nz r4.x + mov r2.z, -r2.z + endif + mul_sat r2.w, r2.w, |r3.y| + and r3.y, r2.y, CB0[0][0].z + movc r3.w, r2.y, l(0), CB0[0][0].w + if_z r2.y + mad r4.y, r2.z, l(0.500000), r0.z + else + mov r4.y, r0.z + endif + if_nz r2.y + mad r4.z, r2.z, l(0.500000), r0.w + else + mov r4.z, r0.w + endif + add r5.xy, -r3.ywyy, r4.yzyy + add r4.yw, r3.yyyw, r4.yyyz + mad r4.z, r2.w, l(-2.000000), l(3.000000) + sample_l r5.z, r5.xyxx, T0[0].xywz, S0[0], l(0.000000) + mul r2.w, r2.w, r2.w + sample_l r5.w, r4.ywyy, T0[0].xyzw, S0[0], l(0.000000) + if_z r4.x + add r3.x, r1.w, r2.x + else + add r3.x, r1.w, r3.x + endif + mul r2.x, r3.z, l(0.250000) + mad r3.z, -r3.x, l(0.500000), r1.w + mul r2.w, r2.w, r4.z + lt r3.z, r3.z, l(0.000000) + mad r6.x, -r3.x, l(0.500000), r5.z + mad r6.y, -r3.x, l(0.500000), r5.w + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(1.500000), r5.x + mad r5.y, -r3.w, l(1.500000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(1.500000), r4.y + mad r4.w, r3.w, l(1.500000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(4.000000), r5.x + mad r5.y, -r3.w, l(4.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(4.000000), r4.y + mad r4.w, r3.w, l(4.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(12.000000), r5.x + mad r5.y, -r3.w, l(12.000000), r5.y + endif + if_nz r4.z + mad r4.y, r3.y, l(12.000000), r4.y + mad r4.w, r3.w, l(12.000000), r4.w + endif + endif + endif + endif + if_z r2.y + mad r2.x, r0.y, CB0[0][0].w, -r5.y + mad r0.x, -r0.y, CB0[0][0].w, r4.w + else + mad r2.x, r0.x, CB0[0][0].z, -r5.x + mad r0.x, -r0.x, CB0[0][0].z, r4.y + endif + lt r3.xy, r6.xyxx, l(0.000000, 0.000000, 0.000000, 0.000000) + add r0.y, r2.x, r0.x + ine r3.xy, r3.zzzz, r3.xyxx + div r0.y, l(1.000000, 1.000000, 1.000000, 1.000000), r0.y + lt r3.z, r2.x, r0.x + min r0.x, r0.x, r2.x + movc r2.x, r3.z, r3.x, r3.y + mul r2.w, r2.w, r2.w + mad r0.x, r0.x, -r0.y, l(0.500000) + mul r0.y, r2.w, l(0.750000) + and r0.x, r0.x, r2.x + max r0.x, r0.y, r0.x + if_z r2.y + mad r0.z, r0.x, r2.z, r0.z + endif + if_nz r2.y + mad r0.w, r0.x, r2.z, r0.w + endif + sample_l r1.xyz, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +endif +mov r1.w, l(1.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw +ret +// Approximately 205 instruction slots used +#endif + +const BYTE fxaa_cs[] = +{ + 68, 88, 66, 67, 146, 66, + 17, 144, 231, 237, 183, 236, + 231, 78, 100, 194, 80, 51, + 78, 217, 1, 0, 0, 0, + 184, 23, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 108, 2, 0, 0, 124, 2, + 0, 0, 140, 2, 0, 0, + 28, 23, 0, 0, 82, 68, + 69, 70, 48, 2, 0, 0, + 1, 0, 0, 0, 44, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 8, 2, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 244, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 115, 97, 109, 112, 108, + 101, 114, 95, 108, 105, 110, + 101, 97, 114, 95, 99, 108, + 97, 109, 112, 0, 120, 101, + 95, 102, 120, 97, 97, 95, + 115, 111, 117, 114, 99, 101, + 0, 120, 101, 95, 102, 120, + 97, 97, 95, 100, 101, 115, + 116, 0, 88, 101, 65, 112, + 112, 108, 121, 71, 97, 109, + 109, 97, 82, 97, 109, 112, + 67, 111, 110, 115, 116, 97, + 110, 116, 115, 0, 171, 171, + 16, 1, 0, 0, 2, 0, + 0, 0, 68, 1, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 1, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 168, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 204, 1, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 102, + 120, 97, 97, 95, 115, 105, + 122, 101, 0, 117, 105, 110, + 116, 50, 0, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 161, 1, 0, 0, 120, 101, + 95, 102, 120, 97, 97, 95, + 115, 105, 122, 101, 95, 105, + 110, 118, 0, 102, 108, 111, + 97, 116, 50, 0, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 136, 20, 0, 0, + 81, 0, 5, 0, 34, 5, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 90, 0, + 0, 6, 70, 110, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 156, 24, 0, 7, + 70, 238, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 17, + 0, 0, 0, 0, 0, 0, + 95, 0, 0, 2, 50, 0, + 2, 0, 104, 0, 0, 2, + 7, 0, 0, 0, 155, 0, + 0, 4, 8, 0, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 0, 80, 0, 0, 8, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 70, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 21, 0, 0, 1, 86, 0, + 0, 4, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 2, 0, 0, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 9, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 0, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 72, 0, 0, 13, 242, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 114, 0, 16, 0, + 2, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 140, 1, 254, + 1, 0, 114, 0, 16, 0, + 3, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 38, 119, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 231, 251, 41, 62, + 0, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 49, 153, 170, 61, + 49, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 0, 3, 58, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 0, 3, + 58, 0, 16, 0, 3, 0, + 0, 0, 72, 0, 0, 142, + 1, 226, 1, 0, 130, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 72, 0, + 0, 142, 1, 62, 0, 0, + 18, 0, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 98, 0, + 16, 0, 4, 0, 0, 0, + 6, 2, 16, 0, 2, 0, + 0, 0, 6, 1, 16, 0, + 3, 0, 0, 0, 14, 0, + 0, 10, 130, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 58, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 12, 98, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 192, 0, 0, 0, 192, + 0, 0, 0, 0, 86, 6, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 10, 0, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 58, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 128, 129, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 11, 130, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 128, 129, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 128, + 129, 0, 0, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 42, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 26, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 8, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 8, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 29, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 42, 0, 16, 0, 3, 0, + 0, 0, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 50, 0, 0, 10, + 34, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 171, 170, 170, 61, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 8, 66, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 8, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 29, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 58, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 52, 0, + 0, 9, 66, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 56, 32, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 9, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 11, 130, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 0, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 42, 0, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 34, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 58, 0, 16, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 5, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 0, 0, 0, 8, + 50, 0, 16, 0, 5, 0, + 0, 0, 214, 5, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 150, 5, 16, 0, + 4, 0, 0, 0, 0, 0, + 0, 7, 162, 0, 16, 0, + 4, 0, 0, 0, 86, 13, + 16, 0, 3, 0, 0, 0, + 86, 9, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 1, 64, 0, 0, 0, 0, + 64, 64, 72, 0, 0, 13, + 66, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 70, 123, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 72, 0, + 0, 13, 130, 0, 16, 0, + 5, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 18, 0, 0, 1, 0, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 56, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 62, 50, 0, + 0, 10, 66, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 10, 18, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 42, 0, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 58, 0, + 16, 0, 5, 0, 0, 0, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 192, 63, 10, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 192, 63, 26, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 192, 63, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 192, 63, 58, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 18, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 54, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 34, 0, + 16, 0, 6, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 198, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 10, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 26, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 64, 10, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 64, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 64, 58, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 18, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 54, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 34, 0, + 16, 0, 6, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 198, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 10, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 26, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 64, 10, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 26, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 64, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 64, 58, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 18, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 54, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 34, 0, + 16, 0, 6, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 198, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 10, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 26, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 64, 65, 10, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 65, 26, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 64, 65, + 26, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 64, 65, + 58, 0, 16, 0, 4, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 31, 0, 0, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 12, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 12, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 58, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 18, 0, 0, 1, 50, 0, + 0, 12, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 5, 0, 0, 0, 50, 0, + 0, 12, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 49, 0, 0, 10, + 50, 0, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 39, 0, + 0, 7, 50, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 14, 0, 0, 10, + 34, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 26, 0, + 16, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 51, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 56, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 63, 1, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 52, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 31, 0, + 0, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 72, 0, 0, 13, 114, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 164, 0, + 0, 7, 242, 224, 33, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 5, 2, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 205, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 94, 0, 0, 0, 1, 0, + 0, 0, 7, 0, 0, 0, + 7, 0, 0, 0, 35, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h new file mode 100644 index 000000000..026ac19fc --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h @@ -0,0 +1,1956 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_fxaa_size; // Offset: 0 Size: 8 +// float2 xe_fxaa_size_inv; // Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_sampler_linear_clamp sampler NA NA S0 s0 1 +// xe_fxaa_source texture float4 2d T0 t0 1 +// xe_fxaa_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_sampler S0[0:0], mode_default, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 7 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +utof r0.xy, vThreadID.xyxx +add r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000) +mul r0.zw, r0.xxxy, CB0[0][0].zzzw +sample_l r1.xyzw, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +gather4 r2.xyz, r0.zwzz, T0[0].xyzw, S0[0].w +gather4_aoffimmi(-1,-1,0) r3.xyz, r0.zwzz, T0[0].zxwy, S0[0].w +max r2.w, r1.w, r2.x +min r3.w, r1.w, r2.x +max r2.w, r2.w, r2.z +min r3.w, r2.z, r3.w +max r4.x, r3.y, r3.x +min r4.y, r3.y, r3.x +max r2.w, r2.w, r4.x +min r3.w, r3.w, r4.y +mul r4.x, r2.w, l(0.063000) +add r2.w, r2.w, -r3.w +max r3.w, r4.x, l(0.031200) +lt r3.w, r2.w, r3.w +if_z r3.w +endif +if_z r3.w + sample_l_aoffimmi(1,-1,0) r3.w, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) + sample_l_aoffimmi(-1,1,0) r4.x, r0.zwzz, T0[0].wxyz, S0[0], l(0.000000) + add r4.yz, r2.xxzx, r3.xxyx + div r2.w, l(1.000000, 1.000000, 1.000000, 1.000000), r2.w + add r4.w, r4.z, r4.y + mad r4.yz, r1.wwww, l(0.000000, -2.000000, -2.000000, 0.000000), r4.yyzy + add r5.x, r2.y, r3.w + add r3.w, r3.w, r3.z + mad r5.y, r2.z, l(-2.000000), r5.x + mad r3.w, r3.x, l(-2.000000), r3.w + add r3.z, r3.z, r4.x + add r2.y, r2.y, r4.x + mad r4.x, |r4.y|, l(2.000000), |r5.y| + mad r3.w, |r4.z|, l(2.000000), |r3.w| + mad r4.y, r3.y, l(-2.000000), r3.z + mad r2.y, r2.x, l(-2.000000), r2.y + add r4.x, r4.x, |r4.y| + add r2.y, r3.w, |r2.y| + add r3.z, r5.x, r3.z + ge r2.y, r4.x, r2.y + mad r3.z, r4.w, l(2.000000), r3.z + if_z r2.y + mov r3.x, r3.y + mov r2.x, r2.z + endif + if_nz r2.y + mov r2.z, CB0[0][0].w + else + mov r2.z, CB0[0][0].z + endif + mad r3.y, r3.z, l(0.083333), -r1.w + add r3.z, -r1.w, r3.x + add r3.w, -r1.w, r2.x + ge r4.x, |r3.z|, |r3.w| + max r3.z, |r3.w|, |r3.z| + if_nz r4.x + mov r2.z, -r2.z + endif + mul_sat r2.w, r2.w, |r3.y| + and r3.y, r2.y, CB0[0][0].z + movc r3.w, r2.y, l(0), CB0[0][0].w + if_z r2.y + mad r4.y, r2.z, l(0.500000), r0.z + else + mov r4.y, r0.z + endif + if_nz r2.y + mad r4.z, r2.z, l(0.500000), r0.w + else + mov r4.z, r0.w + endif + add r5.xy, -r3.ywyy, r4.yzyy + add r4.yw, r3.yyyw, r4.yyyz + mad r4.z, r2.w, l(-2.000000), l(3.000000) + sample_l r5.z, r5.xyxx, T0[0].xywz, S0[0], l(0.000000) + mul r2.w, r2.w, r2.w + sample_l r5.w, r4.ywyy, T0[0].xyzw, S0[0], l(0.000000) + if_z r4.x + add r3.x, r1.w, r2.x + else + add r3.x, r1.w, r3.x + endif + mul r2.x, r3.z, l(0.250000) + mad r3.z, -r3.x, l(0.500000), r1.w + mul r2.w, r2.w, r4.z + lt r3.z, r3.z, l(0.000000) + mad r6.x, -r3.x, l(0.500000), r5.z + mad r6.y, -r3.x, l(0.500000), r5.w + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + add r5.xy, -r3.ywyy, r5.xyxx + endif + or r5.z, r4.z, r4.x + if_nz r4.z + add r4.yw, r3.yyyw, r4.yyyw + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + add r5.xy, -r3.ywyy, r5.xyxx + endif + or r5.z, r4.z, r4.x + if_nz r4.z + add r4.yw, r3.yyyw, r4.yyyw + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + add r5.xy, -r3.ywyy, r5.xyxx + endif + or r5.z, r4.z, r4.x + if_nz r4.z + add r4.yw, r3.yyyw, r4.yyyw + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + add r5.xy, -r3.ywyy, r5.xyxx + endif + or r5.z, r4.z, r4.x + if_nz r4.z + add r4.yw, r3.yyyw, r4.yyyw + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(1.500000), r5.x + mad r5.y, -r3.w, l(1.500000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(1.500000), r4.y + mad r4.w, r3.w, l(1.500000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(4.000000), r5.x + mad r5.y, -r3.w, l(4.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(4.000000), r4.y + mad r4.w, r3.w, l(4.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(8.000000), r5.x + mad r5.y, -r3.w, l(8.000000), r5.y + endif + if_nz r4.z + mad r4.y, r3.y, l(8.000000), r4.y + mad r4.w, r3.w, l(8.000000), r4.w + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + if_z r2.y + mad r2.x, r0.y, CB0[0][0].w, -r5.y + mad r0.x, -r0.y, CB0[0][0].w, r4.w + else + mad r2.x, r0.x, CB0[0][0].z, -r5.x + mad r0.x, -r0.x, CB0[0][0].z, r4.y + endif + lt r3.xy, r6.xyxx, l(0.000000, 0.000000, 0.000000, 0.000000) + add r0.y, r2.x, r0.x + ine r3.xy, r3.zzzz, r3.xyxx + div r0.y, l(1.000000, 1.000000, 1.000000, 1.000000), r0.y + lt r3.z, r2.x, r0.x + min r0.x, r0.x, r2.x + movc r2.x, r3.z, r3.x, r3.y + mul r2.w, r2.w, r2.w + mad r0.x, r0.x, -r0.y, l(0.500000) + and r0.x, r0.x, r2.x + max r0.x, r2.w, r0.x + if_z r2.y + mad r0.z, r0.x, r2.z, r0.z + endif + if_nz r2.y + mad r0.w, r0.x, r2.z, r0.w + endif + sample_l r1.xyz, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +endif +mov r1.w, l(1.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw +ret +// Approximately 364 instruction slots used +#endif + +const BYTE fxaa_extreme_cs[] = +{ + 68, 88, 66, 67, 37, 138, + 209, 45, 7, 149, 158, 200, + 128, 20, 212, 142, 87, 247, + 202, 95, 1, 0, 0, 0, + 16, 36, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 108, 2, 0, 0, 124, 2, + 0, 0, 140, 2, 0, 0, + 116, 35, 0, 0, 82, 68, + 69, 70, 48, 2, 0, 0, + 1, 0, 0, 0, 44, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 8, 2, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 244, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 115, 97, 109, 112, 108, + 101, 114, 95, 108, 105, 110, + 101, 97, 114, 95, 99, 108, + 97, 109, 112, 0, 120, 101, + 95, 102, 120, 97, 97, 95, + 115, 111, 117, 114, 99, 101, + 0, 120, 101, 95, 102, 120, + 97, 97, 95, 100, 101, 115, + 116, 0, 88, 101, 65, 112, + 112, 108, 121, 71, 97, 109, + 109, 97, 82, 97, 109, 112, + 67, 111, 110, 115, 116, 97, + 110, 116, 115, 0, 171, 171, + 16, 1, 0, 0, 2, 0, + 0, 0, 68, 1, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 1, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 168, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 204, 1, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 102, + 120, 97, 97, 95, 115, 105, + 122, 101, 0, 117, 105, 110, + 116, 50, 0, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 161, 1, 0, 0, 120, 101, + 95, 102, 120, 97, 97, 95, + 115, 105, 122, 101, 95, 105, + 110, 118, 0, 102, 108, 111, + 97, 116, 50, 0, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 224, 32, 0, 0, + 81, 0, 5, 0, 56, 8, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 90, 0, + 0, 6, 70, 110, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 156, 24, 0, 7, + 70, 238, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 17, + 0, 0, 0, 0, 0, 0, + 95, 0, 0, 2, 50, 0, + 2, 0, 104, 0, 0, 2, + 7, 0, 0, 0, 155, 0, + 0, 4, 8, 0, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 0, 80, 0, 0, 8, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 70, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 21, 0, 0, 1, 86, 0, + 0, 4, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 2, 0, 0, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 9, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 0, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 72, 0, 0, 13, 242, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 114, 0, 16, 0, + 2, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 140, 1, 254, + 1, 0, 114, 0, 16, 0, + 3, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 38, 119, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 37, 6, 129, 61, + 0, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 36, 151, 255, 60, + 49, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 0, 3, 58, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 0, 3, + 58, 0, 16, 0, 3, 0, + 0, 0, 72, 0, 0, 142, + 1, 226, 1, 0, 130, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 72, 0, + 0, 142, 1, 62, 0, 0, + 18, 0, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 98, 0, + 16, 0, 4, 0, 0, 0, + 6, 2, 16, 0, 2, 0, + 0, 0, 6, 1, 16, 0, + 3, 0, 0, 0, 14, 0, + 0, 10, 130, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 58, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 12, 98, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 192, 0, 0, 0, 192, + 0, 0, 0, 0, 86, 6, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 10, 0, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 58, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 128, 129, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 11, 130, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 128, 129, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 128, + 129, 0, 0, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 42, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 26, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 8, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 8, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 29, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 42, 0, 16, 0, 3, 0, + 0, 0, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 50, 0, 0, 10, + 34, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 171, 170, 170, 61, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 8, 66, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 8, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 29, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 58, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 52, 0, + 0, 9, 66, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 56, 32, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 9, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 11, 130, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 0, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 42, 0, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 34, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 58, 0, 16, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 5, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 0, 0, 0, 8, + 50, 0, 16, 0, 5, 0, + 0, 0, 214, 5, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 150, 5, 16, 0, + 4, 0, 0, 0, 0, 0, + 0, 7, 162, 0, 16, 0, + 4, 0, 0, 0, 86, 13, + 16, 0, 3, 0, 0, 0, + 86, 9, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 1, 64, 0, 0, 0, 0, + 64, 64, 72, 0, 0, 13, + 66, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 70, 123, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 72, 0, + 0, 13, 130, 0, 16, 0, + 5, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 18, 0, 0, 1, 0, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 56, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 62, 50, 0, + 0, 10, 66, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 10, 18, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 42, 0, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 58, 0, + 16, 0, 5, 0, 0, 0, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 8, + 50, 0, 16, 0, 5, 0, + 0, 0, 214, 5, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 162, 0, + 16, 0, 4, 0, 0, 0, + 86, 13, 16, 0, 3, 0, + 0, 0, 86, 13, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 8, 50, 0, + 16, 0, 5, 0, 0, 0, + 214, 5, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 0, 0, + 0, 7, 162, 0, 16, 0, + 4, 0, 0, 0, 86, 13, + 16, 0, 3, 0, 0, 0, + 86, 13, 16, 0, 4, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 5, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 18, 0, + 16, 0, 6, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 54, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 34, 0, 16, 0, 6, 0, + 0, 0, 214, 5, 16, 0, + 4, 0, 0, 0, 198, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 18, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 10, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 26, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 49, 0, 0, 8, + 82, 0, 16, 0, 4, 0, + 0, 0, 6, 1, 16, 128, + 129, 0, 0, 0, 6, 0, + 0, 0, 6, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 0, 0, + 0, 8, 50, 0, 16, 0, + 5, 0, 0, 0, 214, 5, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 21, 0, 0, 1, 60, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 162, 0, 16, 0, 4, 0, + 0, 0, 86, 13, 16, 0, + 3, 0, 0, 0, 86, 13, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 18, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 54, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 34, 0, + 16, 0, 6, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 198, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 10, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 26, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 8, + 50, 0, 16, 0, 5, 0, + 0, 0, 214, 5, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 162, 0, + 16, 0, 4, 0, 0, 0, + 86, 13, 16, 0, 3, 0, + 0, 0, 86, 13, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 192, 63, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 192, 63, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 192, 63, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 192, 63, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 65, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 65, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 65, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 65, 58, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 12, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 5, 0, + 0, 0, 50, 0, 0, 12, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 18, 0, 0, 1, + 50, 0, 0, 12, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 42, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 12, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 10, 50, 0, 16, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 39, 0, 0, 7, 50, 0, + 16, 0, 3, 0, 0, 0, + 166, 10, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 14, 0, + 0, 10, 34, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 26, 0, 16, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 51, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 1, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 72, 0, + 0, 13, 114, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 164, 0, 0, 7, + 242, 224, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 5, 2, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 108, 1, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 134, 0, + 0, 0, 1, 0, 0, 0, + 14, 0, 0, 0, 7, 0, + 0, 0, 84, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_1xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_1xmsaa_cs.h index b4022a12a..3e43288af 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_1xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_1xmsaa_cs.h @@ -100,10 +100,10 @@ ret const BYTE host_depth_store_1xmsaa_cs[] = { - 68, 88, 66, 67, 40, 219, - 237, 83, 207, 54, 217, 154, - 183, 72, 124, 224, 242, 47, - 153, 1, 1, 0, 0, 0, + 68, 88, 66, 67, 240, 197, + 52, 115, 102, 12, 206, 220, + 26, 47, 204, 31, 163, 187, + 103, 82, 1, 0, 0, 0, 196, 9, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 2, 0, 0, 188, 2, @@ -113,7 +113,7 @@ const BYTE host_depth_store_1xmsaa_cs[] = 2, 0, 0, 0, 92, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 70, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_2xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_2xmsaa_cs.h index 21f6ce603..16d7d51b2 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_2xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_2xmsaa_cs.h @@ -113,10 +113,10 @@ ret const BYTE host_depth_store_2xmsaa_cs[] = { - 68, 88, 66, 67, 238, 111, - 30, 240, 147, 73, 122, 32, - 177, 28, 116, 35, 239, 195, - 44, 205, 1, 0, 0, 0, + 68, 88, 66, 67, 220, 153, + 96, 168, 160, 176, 100, 61, + 221, 246, 187, 57, 87, 53, + 74, 27, 1, 0, 0, 0, 104, 11, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 2, 0, 0, 188, 2, @@ -126,7 +126,7 @@ const BYTE host_depth_store_2xmsaa_cs[] = 2, 0, 0, 0, 92, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 70, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_4xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_4xmsaa_cs.h index 5ba206a86..0ff471cc5 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_4xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_4xmsaa_cs.h @@ -102,10 +102,10 @@ ret const BYTE host_depth_store_4xmsaa_cs[] = { - 68, 88, 66, 67, 2, 59, - 173, 180, 27, 122, 26, 189, - 176, 122, 66, 167, 148, 57, - 133, 176, 1, 0, 0, 0, + 68, 88, 66, 67, 255, 93, + 213, 231, 110, 151, 46, 65, + 140, 74, 54, 254, 196, 135, + 241, 89, 1, 0, 0, 0, 72, 10, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 2, 0, 0, 188, 2, @@ -115,7 +115,7 @@ const BYTE host_depth_store_4xmsaa_cs[] = 2, 0, 0, 0, 92, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 70, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/passthrough_position_xy_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/passthrough_position_xy_vs.h index 6e58bc909..a5f7f58b8 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/passthrough_position_xy_vs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/passthrough_position_xy_vs.h @@ -29,10 +29,10 @@ ret const BYTE passthrough_position_xy_vs[] = { - 68, 88, 66, 67, 228, 252, - 150, 103, 204, 200, 35, 231, - 157, 180, 182, 79, 123, 204, - 157, 78, 1, 0, 0, 0, + 68, 88, 66, 67, 92, 220, + 0, 199, 190, 67, 183, 153, + 171, 192, 4, 39, 67, 55, + 215, 255, 1, 0, 0, 0, 12, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 212, 0, @@ -42,7 +42,7 @@ const BYTE passthrough_position_xy_vs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, + 254, 255, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h index 05adda89b..a8a356706 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h @@ -273,10 +273,10 @@ ret const BYTE primitive_point_list_gs[] = { - 68, 88, 66, 67, 22, 253, - 167, 182, 60, 53, 75, 37, - 178, 38, 230, 182, 97, 141, - 160, 120, 1, 0, 0, 0, + 68, 88, 66, 67, 6, 119, + 40, 99, 120, 121, 153, 224, + 111, 77, 187, 15, 15, 245, + 37, 128, 1, 0, 0, 0, 136, 29, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 184, 10, 0, 0, 248, 12, @@ -286,7 +286,7 @@ const BYTE primitive_point_list_gs[] = 1, 0, 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 71, 0, 5, 4, 0, + 83, 71, 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h index ac77eae81..e349a4f47 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h @@ -194,10 +194,10 @@ ret const BYTE primitive_quad_list_gs[] = { - 68, 88, 66, 67, 60, 29, - 113, 120, 166, 105, 127, 75, - 174, 160, 2, 184, 182, 91, - 66, 12, 1, 0, 0, 0, + 68, 88, 66, 67, 26, 143, + 179, 72, 238, 147, 43, 130, + 37, 11, 116, 191, 138, 68, + 255, 76, 1, 0, 0, 0, 36, 16, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 224, 2, @@ -207,7 +207,7 @@ const BYTE primitive_quad_list_gs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 71, 0, 5, 4, 0, + 83, 71, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h index 6ce8c711d..4c078e6ed 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h @@ -424,10 +424,10 @@ ret const BYTE primitive_rectangle_list_gs[] = { - 68, 88, 66, 67, 8, 81, - 101, 117, 123, 39, 249, 189, - 184, 94, 218, 115, 216, 148, - 125, 96, 1, 0, 0, 0, + 68, 88, 66, 67, 84, 207, + 1, 11, 213, 109, 28, 213, + 94, 110, 135, 167, 112, 243, + 154, 30, 1, 0, 0, 0, 68, 40, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 224, 2, @@ -437,7 +437,7 @@ const BYTE primitive_rectangle_list_gs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 71, 0, 5, 4, 0, + 83, 71, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h index 960fc26a4..cc4b6ddd1 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h @@ -80,10 +80,10 @@ ret const BYTE resolve_clear_32bpp_cs[] = { - 68, 88, 66, 67, 212, 33, - 57, 169, 71, 99, 28, 75, - 202, 138, 254, 170, 245, 39, - 113, 44, 1, 0, 0, 0, + 68, 88, 66, 67, 226, 247, + 125, 160, 57, 195, 118, 226, + 52, 138, 250, 148, 103, 90, + 91, 213, 1, 0, 0, 0, 120, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 64, 2, 0, 0, 80, 2, @@ -93,7 +93,7 @@ const BYTE resolve_clear_32bpp_cs[] = 1, 0, 0, 0, 176, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 220, 1, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_scaled_cs.h index 03fdb042d..2afb65467 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_scaled_cs.h @@ -100,10 +100,10 @@ ret const BYTE resolve_clear_32bpp_scaled_cs[] = { - 68, 88, 66, 67, 151, 173, - 156, 244, 183, 241, 226, 31, - 214, 214, 54, 114, 10, 217, - 153, 194, 1, 0, 0, 0, + 68, 88, 66, 67, 205, 174, + 123, 5, 98, 198, 38, 143, + 98, 109, 190, 150, 214, 170, + 216, 92, 1, 0, 0, 0, 104, 9, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 228, 2, 0, 0, 244, 2, @@ -113,7 +113,7 @@ const BYTE resolve_clear_32bpp_scaled_cs[] = 2, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 128, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h index 25c2c75c5..c50250e97 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h @@ -79,10 +79,10 @@ ret const BYTE resolve_clear_64bpp_cs[] = { - 68, 88, 66, 67, 11, 134, - 106, 112, 85, 206, 144, 113, - 121, 69, 237, 199, 49, 129, - 4, 62, 1, 0, 0, 0, + 68, 88, 66, 67, 16, 5, + 27, 66, 247, 175, 170, 221, + 90, 253, 80, 46, 104, 119, + 87, 139, 1, 0, 0, 0, 148, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 64, 2, 0, 0, 80, 2, @@ -92,7 +92,7 @@ const BYTE resolve_clear_64bpp_cs[] = 1, 0, 0, 0, 176, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 220, 1, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_scaled_cs.h index af43268c5..8db3ee557 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_scaled_cs.h @@ -98,10 +98,10 @@ ret const BYTE resolve_clear_64bpp_scaled_cs[] = { - 68, 88, 66, 67, 226, 249, - 231, 177, 11, 141, 42, 153, - 99, 45, 131, 104, 152, 194, - 26, 176, 1, 0, 0, 0, + 68, 88, 66, 67, 246, 14, + 132, 223, 204, 44, 6, 28, + 86, 181, 216, 251, 242, 62, + 34, 31, 1, 0, 0, 0, 112, 9, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 228, 2, 0, 0, 244, 2, @@ -111,7 +111,7 @@ const BYTE resolve_clear_64bpp_scaled_cs[] = 2, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 128, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h index c188bb822..4205ee54f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h @@ -214,10 +214,10 @@ ret const BYTE resolve_fast_32bpp_1x2xmsaa_cs[] = { - 68, 88, 66, 67, 155, 144, - 108, 102, 32, 219, 74, 112, - 191, 128, 193, 179, 111, 166, - 110, 225, 1, 0, 0, 0, + 68, 88, 66, 67, 239, 168, + 103, 4, 189, 160, 141, 83, + 16, 65, 33, 184, 201, 9, + 185, 83, 1, 0, 0, 0, 156, 24, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -227,7 +227,7 @@ const BYTE resolve_fast_32bpp_1x2xmsaa_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_scaled_cs.h index 146f231b0..227c58ca3 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_scaled_cs.h @@ -278,10 +278,10 @@ ret const BYTE resolve_fast_32bpp_1x2xmsaa_scaled_cs[] = { - 68, 88, 66, 67, 145, 228, - 65, 128, 86, 250, 142, 70, - 190, 88, 12, 69, 154, 111, - 98, 110, 1, 0, 0, 0, + 68, 88, 66, 67, 33, 171, + 235, 222, 88, 49, 17, 196, + 69, 254, 64, 92, 43, 122, + 25, 15, 1, 0, 0, 0, 40, 31, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -291,7 +291,7 @@ const BYTE resolve_fast_32bpp_1x2xmsaa_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h index b78967304..1de49b65a 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h @@ -225,10 +225,10 @@ ret const BYTE resolve_fast_32bpp_4xmsaa_cs[] = { - 68, 88, 66, 67, 83, 123, - 16, 172, 13, 23, 165, 181, - 111, 176, 230, 199, 227, 113, - 202, 160, 1, 0, 0, 0, + 68, 88, 66, 67, 170, 85, + 205, 145, 228, 207, 40, 6, + 92, 178, 101, 253, 108, 144, + 148, 218, 1, 0, 0, 0, 196, 25, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -238,7 +238,7 @@ const BYTE resolve_fast_32bpp_4xmsaa_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_scaled_cs.h index dd885ae7a..48e3dda10 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_scaled_cs.h @@ -290,10 +290,10 @@ ret const BYTE resolve_fast_32bpp_4xmsaa_scaled_cs[] = { - 68, 88, 66, 67, 31, 111, - 219, 218, 202, 212, 228, 164, - 35, 4, 215, 208, 98, 172, - 195, 246, 1, 0, 0, 0, + 68, 88, 66, 67, 228, 200, + 92, 46, 175, 37, 210, 169, + 116, 188, 100, 167, 120, 186, + 226, 184, 1, 0, 0, 0, 100, 32, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -303,7 +303,7 @@ const BYTE resolve_fast_32bpp_4xmsaa_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h index 06bd84852..827dbd661 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h @@ -203,10 +203,10 @@ ret const BYTE resolve_fast_64bpp_1x2xmsaa_cs[] = { - 68, 88, 66, 67, 148, 119, - 138, 27, 157, 3, 164, 49, - 44, 31, 102, 96, 70, 236, - 100, 146, 1, 0, 0, 0, + 68, 88, 66, 67, 6, 88, + 245, 144, 16, 3, 175, 59, + 111, 160, 2, 183, 105, 216, + 39, 35, 1, 0, 0, 0, 16, 23, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -216,7 +216,7 @@ const BYTE resolve_fast_64bpp_1x2xmsaa_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_scaled_cs.h index dca0ec999..d957d07a4 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_scaled_cs.h @@ -265,10 +265,10 @@ ret const BYTE resolve_fast_64bpp_1x2xmsaa_scaled_cs[] = { - 68, 88, 66, 67, 146, 74, - 159, 181, 129, 209, 232, 153, - 8, 178, 69, 215, 5, 127, - 187, 119, 1, 0, 0, 0, + 68, 88, 66, 67, 217, 58, + 225, 5, 83, 76, 76, 76, + 41, 4, 184, 58, 64, 138, + 164, 215, 1, 0, 0, 0, 24, 29, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -278,7 +278,7 @@ const BYTE resolve_fast_64bpp_1x2xmsaa_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h index 8d109abf3..6d0167148 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h @@ -204,10 +204,10 @@ ret const BYTE resolve_fast_64bpp_4xmsaa_cs[] = { - 68, 88, 66, 67, 103, 127, - 24, 191, 130, 242, 189, 20, - 38, 18, 213, 75, 35, 175, - 132, 194, 1, 0, 0, 0, + 68, 88, 66, 67, 219, 212, + 228, 165, 45, 17, 135, 148, + 112, 245, 209, 7, 35, 133, + 189, 71, 1, 0, 0, 0, 40, 23, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -217,7 +217,7 @@ const BYTE resolve_fast_64bpp_4xmsaa_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_scaled_cs.h index 8da74d9b4..c3155881e 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_scaled_cs.h @@ -263,10 +263,10 @@ ret const BYTE resolve_fast_64bpp_4xmsaa_scaled_cs[] = { - 68, 88, 66, 67, 175, 243, - 135, 222, 141, 148, 29, 126, - 11, 2, 155, 131, 194, 117, - 96, 179, 1, 0, 0, 0, + 68, 88, 66, 67, 128, 163, + 164, 187, 116, 154, 133, 40, + 143, 38, 115, 1, 152, 118, + 125, 200, 1, 0, 0, 0, 36, 29, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -276,7 +276,7 @@ const BYTE resolve_fast_64bpp_4xmsaa_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h index 8c891d214..3dcc2a0fc 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h @@ -797,10 +797,10 @@ ret const BYTE resolve_full_128bpp_cs[] = { - 68, 88, 66, 67, 138, 187, - 29, 190, 119, 248, 103, 130, - 145, 38, 138, 150, 199, 99, - 88, 186, 1, 0, 0, 0, + 68, 88, 66, 67, 21, 9, + 61, 18, 132, 97, 176, 57, + 19, 100, 60, 248, 43, 42, + 194, 237, 1, 0, 0, 0, 156, 86, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -810,7 +810,7 @@ const BYTE resolve_full_128bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_scaled_cs.h index 55de6d907..33a40c184 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_scaled_cs.h @@ -858,10 +858,10 @@ ret const BYTE resolve_full_128bpp_scaled_cs[] = { - 68, 88, 66, 67, 252, 54, - 64, 236, 181, 3, 56, 102, - 51, 248, 62, 205, 28, 164, - 215, 11, 1, 0, 0, 0, + 68, 88, 66, 67, 0, 197, + 108, 112, 31, 221, 155, 150, + 192, 148, 203, 210, 205, 214, + 112, 66, 1, 0, 0, 0, 220, 91, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -871,7 +871,7 @@ const BYTE resolve_full_128bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h index 6d6a4feb6..cfeca33cb 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h @@ -1350,10 +1350,10 @@ ret const BYTE resolve_full_16bpp_cs[] = { - 68, 88, 66, 67, 85, 89, - 112, 166, 132, 95, 159, 158, - 148, 255, 182, 126, 49, 65, - 238, 68, 1, 0, 0, 0, + 68, 88, 66, 67, 122, 248, + 161, 239, 38, 34, 59, 122, + 64, 201, 159, 30, 45, 236, + 145, 6, 1, 0, 0, 0, 112, 158, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -1363,7 +1363,7 @@ const BYTE resolve_full_16bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_scaled_cs.h index e1252bd02..189c65905 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_scaled_cs.h @@ -1382,10 +1382,10 @@ ret const BYTE resolve_full_16bpp_scaled_cs[] = { - 68, 88, 66, 67, 24, 35, - 27, 103, 137, 85, 99, 31, - 248, 119, 100, 82, 1, 5, - 211, 65, 1, 0, 0, 0, + 68, 88, 66, 67, 17, 196, + 248, 162, 148, 187, 123, 170, + 150, 149, 87, 23, 157, 34, + 89, 51, 1, 0, 0, 0, 188, 160, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -1395,7 +1395,7 @@ const BYTE resolve_full_16bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h index e5857d3e0..3c923d804 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h @@ -1354,10 +1354,10 @@ ret const BYTE resolve_full_32bpp_cs[] = { - 68, 88, 66, 67, 191, 202, - 187, 105, 122, 172, 254, 124, - 230, 42, 42, 152, 112, 61, - 118, 194, 1, 0, 0, 0, + 68, 88, 66, 67, 6, 223, + 221, 81, 201, 228, 242, 38, + 30, 228, 108, 198, 29, 216, + 108, 219, 1, 0, 0, 0, 220, 157, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -1367,7 +1367,7 @@ const BYTE resolve_full_32bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_scaled_cs.h index 1d0a0d2fe..89ca2467e 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_scaled_cs.h @@ -1397,10 +1397,10 @@ ret const BYTE resolve_full_32bpp_scaled_cs[] = { - 68, 88, 66, 67, 159, 80, - 95, 78, 198, 213, 86, 238, - 93, 9, 250, 90, 57, 206, - 56, 203, 1, 0, 0, 0, + 68, 88, 66, 67, 19, 170, + 1, 90, 249, 15, 80, 164, + 255, 208, 31, 117, 114, 147, + 62, 94, 1, 0, 0, 0, 4, 162, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -1410,7 +1410,7 @@ const BYTE resolve_full_32bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h index b8e43bbe1..eb712a645 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h @@ -1275,10 +1275,10 @@ ret const BYTE resolve_full_64bpp_cs[] = { - 68, 88, 66, 67, 123, 61, - 63, 178, 155, 115, 88, 68, - 202, 19, 87, 198, 58, 252, - 174, 110, 1, 0, 0, 0, + 68, 88, 66, 67, 87, 220, + 183, 187, 206, 232, 244, 147, + 255, 195, 21, 134, 69, 222, + 224, 255, 1, 0, 0, 0, 232, 147, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -1288,7 +1288,7 @@ const BYTE resolve_full_64bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_scaled_cs.h index 085b4df2e..3bd227749 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_scaled_cs.h @@ -1338,10 +1338,10 @@ ret const BYTE resolve_full_64bpp_scaled_cs[] = { - 68, 88, 66, 67, 192, 10, - 30, 169, 238, 27, 64, 245, - 27, 79, 191, 206, 88, 74, - 18, 223, 1, 0, 0, 0, + 68, 88, 66, 67, 60, 118, + 161, 100, 5, 152, 135, 130, + 31, 41, 169, 237, 170, 21, + 198, 182, 1, 0, 0, 0, 216, 153, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -1351,7 +1351,7 @@ const BYTE resolve_full_64bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h index d1b5e34c1..b1a8c9c74 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h @@ -678,10 +678,10 @@ ret const BYTE resolve_full_8bpp_cs[] = { - 68, 88, 66, 67, 253, 28, - 166, 242, 173, 99, 18, 102, - 240, 221, 130, 124, 127, 224, - 31, 30, 1, 0, 0, 0, + 68, 88, 66, 67, 160, 163, + 233, 191, 143, 128, 203, 231, + 48, 167, 197, 167, 225, 27, + 77, 108, 1, 0, 0, 0, 196, 76, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -691,7 +691,7 @@ const BYTE resolve_full_8bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h index 0cc4578ad..5801deccd 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h @@ -720,10 +720,10 @@ ret const BYTE resolve_full_8bpp_scaled_cs[] = { - 68, 88, 66, 67, 162, 175, - 232, 246, 251, 37, 158, 3, - 20, 94, 73, 161, 62, 53, - 31, 163, 1, 0, 0, 0, + 68, 88, 66, 67, 143, 238, + 173, 2, 246, 240, 28, 191, + 52, 72, 53, 243, 190, 87, + 239, 146, 1, 0, 0, 0, 200, 80, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -733,7 +733,7 @@ const BYTE resolve_full_8bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h deleted file mode 100644 index 34b882a0d..000000000 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h +++ /dev/null @@ -1,167 +0,0 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 10.1 -// -// -// Resource Bindings: -// -// Name Type Format Dim ID HLSL Bind Count -// ------------------------------ ---------- ------- ----------- ------- -------------- ------ -// xe_sampler_linear_clamp sampler NA NA S0 s0 1 -// xe_texture texture float3 2d T0 t0 1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// TEXCOORD 0 xy 0 NONE float xy -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Target 0 xyzw 0 TARGET float xyzw -// -ps_5_1 -dcl_globalFlags refactoringAllowed -dcl_sampler S0[0:0], mode_default, space=0 -dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 -dcl_input_ps linear v0.xy -dcl_output o0.xyzw -dcl_temps 1 -sample_l r0.xyz, v0.xyxx, T0[0].xyzw, S0[0], l(0.000000) -mov o0.xyz, r0.xyzx -mov o0.w, l(1.000000) -ret -// Approximately 4 instruction slots used -#endif - -const BYTE stretch_ps[] = -{ - 68, 88, 66, 67, 42, 105, - 40, 75, 32, 223, 178, 162, - 221, 190, 237, 193, 82, 219, - 83, 57, 1, 0, 0, 0, - 224, 2, 0, 0, 5, 0, - 0, 0, 52, 0, 0, 0, - 20, 1, 0, 0, 72, 1, - 0, 0, 124, 1, 0, 0, - 68, 2, 0, 0, 82, 68, - 69, 70, 216, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, - 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, - 175, 0, 0, 0, 19, 19, - 68, 37, 60, 0, 0, 0, - 24, 0, 0, 0, 40, 0, - 0, 0, 40, 0, 0, 0, - 36, 0, 0, 0, 12, 0, - 0, 0, 0, 0, 0, 0, - 140, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 164, 0, - 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 0, 0, 0, 0, 1, 0, - 0, 0, 8, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 120, 101, 95, 115, - 97, 109, 112, 108, 101, 114, - 95, 108, 105, 110, 101, 97, - 114, 95, 99, 108, 97, 109, - 112, 0, 120, 101, 95, 116, - 101, 120, 116, 117, 114, 101, - 0, 77, 105, 99, 114, 111, - 115, 111, 102, 116, 32, 40, - 82, 41, 32, 72, 76, 83, - 76, 32, 83, 104, 97, 100, - 101, 114, 32, 67, 111, 109, - 112, 105, 108, 101, 114, 32, - 49, 48, 46, 49, 0, 171, - 73, 83, 71, 78, 44, 0, - 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 32, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 3, 3, 0, 0, 84, 69, - 88, 67, 79, 79, 82, 68, - 0, 171, 171, 171, 79, 83, - 71, 78, 44, 0, 0, 0, - 1, 0, 0, 0, 8, 0, - 0, 0, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 15, 0, - 0, 0, 83, 86, 95, 84, - 97, 114, 103, 101, 116, 0, - 171, 171, 83, 72, 69, 88, - 192, 0, 0, 0, 81, 0, - 0, 0, 48, 0, 0, 0, - 106, 8, 0, 1, 90, 0, - 0, 6, 70, 110, 48, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 88, 24, - 0, 7, 70, 126, 48, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 85, 85, 0, 0, 0, 0, - 0, 0, 98, 16, 0, 3, - 50, 16, 16, 0, 0, 0, - 0, 0, 101, 0, 0, 3, - 242, 32, 16, 0, 0, 0, - 0, 0, 104, 0, 0, 2, - 1, 0, 0, 0, 72, 0, - 0, 13, 114, 0, 16, 0, - 0, 0, 0, 0, 70, 16, - 16, 0, 0, 0, 0, 0, - 70, 126, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 96, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 64, 0, 0, 0, 0, - 0, 0, 54, 0, 0, 5, - 114, 32, 16, 0, 0, 0, - 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 54, 0, - 0, 5, 130, 32, 16, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 128, 63, - 62, 0, 0, 1, 83, 84, - 65, 84, 148, 0, 0, 0, - 4, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 -}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_adaptive_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_adaptive_vs.h index 4c69634b8..a80df6cfc 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_adaptive_vs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_adaptive_vs.h @@ -94,10 +94,10 @@ ret const BYTE tessellation_adaptive_vs[] = { - 68, 88, 66, 67, 223, 69, - 21, 252, 96, 81, 180, 155, - 11, 146, 181, 238, 118, 211, - 188, 154, 1, 0, 0, 0, + 68, 88, 66, 67, 75, 49, + 78, 76, 10, 94, 91, 100, + 187, 17, 145, 80, 196, 255, + 224, 35, 1, 0, 0, 0, 196, 13, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 184, 10, 0, 0, 236, 10, @@ -107,7 +107,7 @@ const BYTE tessellation_adaptive_vs[] = 1, 0, 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, + 254, 255, 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_indexed_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_indexed_vs.h index d5126c625..5362ad6fe 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_indexed_vs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_indexed_vs.h @@ -96,10 +96,10 @@ ret const BYTE tessellation_indexed_vs[] = { - 68, 88, 66, 67, 6, 210, - 5, 58, 145, 186, 106, 71, - 191, 85, 65, 89, 187, 76, - 25, 50, 1, 0, 0, 0, + 68, 88, 66, 67, 126, 143, + 61, 16, 42, 166, 147, 123, + 54, 196, 251, 250, 225, 235, + 160, 249, 1, 0, 0, 0, 248, 13, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 184, 10, 0, 0, 236, 10, @@ -109,7 +109,7 @@ const BYTE tessellation_indexed_vs[] = 1, 0, 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, + 254, 255, 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h index 73b94fb24..4d3c417b7 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_128bpb_cs[] = { - 68, 88, 66, 67, 69, 109, - 54, 62, 246, 252, 13, 179, - 61, 140, 108, 218, 151, 23, - 217, 10, 1, 0, 0, 0, + 68, 88, 66, 67, 202, 63, + 252, 201, 70, 118, 107, 252, + 56, 217, 121, 32, 214, 118, + 48, 42, 1, 0, 0, 0, 92, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_128bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h index 9b102e5b3..ab9c0540c 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h @@ -175,10 +175,10 @@ ret const BYTE texture_load_128bpb_scaled_cs[] = { - 68, 88, 66, 67, 152, 21, - 0, 244, 101, 90, 251, 167, - 33, 145, 108, 252, 235, 186, - 133, 5, 1, 0, 0, 0, + 68, 88, 66, 67, 0, 151, + 15, 173, 246, 165, 135, 120, + 79, 233, 110, 0, 24, 192, + 65, 142, 1, 0, 0, 0, 160, 20, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -188,7 +188,7 @@ const BYTE texture_load_128bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h index e9e64685f..880b2d954 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h @@ -150,10 +150,10 @@ ret const BYTE texture_load_16bpb_cs[] = { - 68, 88, 66, 67, 174, 93, - 70, 99, 109, 104, 7, 76, - 197, 223, 164, 98, 22, 191, - 35, 145, 1, 0, 0, 0, + 68, 88, 66, 67, 241, 108, + 80, 210, 39, 187, 91, 178, + 204, 21, 81, 58, 61, 11, + 55, 221, 1, 0, 0, 0, 28, 17, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -163,7 +163,7 @@ const BYTE texture_load_16bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h index 488d317d3..b7e86471d 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h @@ -163,10 +163,10 @@ ret const BYTE texture_load_16bpb_scaled_cs[] = { - 68, 88, 66, 67, 81, 210, - 211, 210, 188, 152, 146, 59, - 242, 122, 231, 17, 215, 172, - 246, 100, 1, 0, 0, 0, + 68, 88, 66, 67, 194, 117, + 247, 194, 178, 87, 120, 28, + 79, 25, 94, 189, 238, 128, + 139, 128, 1, 0, 0, 0, 0, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -176,7 +176,7 @@ const BYTE texture_load_16bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h index c5a0d2816..db483628e 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h @@ -161,10 +161,10 @@ ret const BYTE texture_load_32bpb_cs[] = { - 68, 88, 66, 67, 127, 41, - 115, 152, 37, 92, 49, 26, - 80, 31, 185, 102, 249, 41, - 197, 36, 1, 0, 0, 0, + 68, 88, 66, 67, 147, 100, + 112, 89, 242, 160, 225, 236, + 154, 215, 131, 75, 212, 235, + 15, 182, 1, 0, 0, 0, 204, 18, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -174,7 +174,7 @@ const BYTE texture_load_32bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h index 2619fa2f4..c4be248cc 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h @@ -180,10 +180,10 @@ ret const BYTE texture_load_32bpb_scaled_cs[] = { - 68, 88, 66, 67, 213, 122, - 184, 211, 188, 144, 40, 184, - 157, 227, 165, 48, 220, 115, - 140, 200, 1, 0, 0, 0, + 68, 88, 66, 67, 218, 190, + 24, 130, 153, 203, 104, 119, + 33, 181, 7, 206, 254, 211, + 212, 77, 1, 0, 0, 0, 108, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -193,7 +193,7 @@ const BYTE texture_load_32bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h index 8f5da5ce0..7a37abea3 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_64bpb_cs[] = { - 68, 88, 66, 67, 58, 78, - 250, 228, 232, 27, 64, 158, - 177, 203, 109, 154, 100, 33, - 245, 49, 1, 0, 0, 0, + 68, 88, 66, 67, 92, 16, + 243, 45, 89, 227, 7, 187, + 59, 197, 251, 47, 47, 108, + 92, 190, 1, 0, 0, 0, 104, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_64bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h index 39c9a6d0a..61aad6d3f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h @@ -180,10 +180,10 @@ ret const BYTE texture_load_64bpb_scaled_cs[] = { - 68, 88, 66, 67, 146, 51, - 188, 210, 64, 194, 16, 242, - 150, 245, 136, 237, 175, 242, - 242, 204, 1, 0, 0, 0, + 68, 88, 66, 67, 129, 207, + 119, 119, 100, 163, 90, 188, + 114, 227, 54, 159, 242, 90, + 188, 99, 1, 0, 0, 0, 108, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -193,7 +193,7 @@ const BYTE texture_load_64bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h index 5dfaf8bb6..7d294832c 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h @@ -139,10 +139,10 @@ ret const BYTE texture_load_8bpb_cs[] = { - 68, 88, 66, 67, 94, 187, - 134, 253, 107, 160, 196, 222, - 117, 123, 98, 19, 188, 66, - 171, 48, 1, 0, 0, 0, + 68, 88, 66, 67, 78, 119, + 192, 2, 178, 124, 184, 10, + 189, 127, 69, 194, 97, 210, + 18, 48, 1, 0, 0, 0, 36, 16, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -152,7 +152,7 @@ const BYTE texture_load_8bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h index 855c58e75..4a3f556f9 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h @@ -151,10 +151,10 @@ ret const BYTE texture_load_8bpb_scaled_cs[] = { - 68, 88, 66, 67, 240, 96, - 141, 60, 254, 240, 162, 218, - 255, 165, 237, 94, 178, 76, - 40, 219, 1, 0, 0, 0, + 68, 88, 66, 67, 104, 142, + 181, 219, 239, 205, 13, 249, + 232, 59, 4, 117, 104, 185, + 138, 244, 1, 0, 0, 0, 252, 17, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -164,7 +164,7 @@ const BYTE texture_load_8bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h index a275eadb2..706bee507 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h @@ -498,10 +498,10 @@ ret const BYTE texture_load_ctx1_cs[] = { - 68, 88, 66, 67, 218, 197, - 112, 160, 14, 201, 105, 66, - 53, 47, 83, 103, 144, 212, - 96, 106, 1, 0, 0, 0, + 68, 88, 66, 67, 224, 177, + 169, 46, 201, 156, 106, 177, + 123, 25, 97, 64, 20, 172, + 37, 106, 1, 0, 0, 0, 116, 65, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -511,7 +511,7 @@ const BYTE texture_load_ctx1_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h index 8dced34cb..143b2359f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h @@ -193,10 +193,10 @@ ret const BYTE texture_load_depth_float_cs[] = { - 68, 88, 66, 67, 204, 91, - 20, 67, 68, 27, 100, 159, - 55, 40, 24, 32, 240, 93, - 21, 161, 1, 0, 0, 0, + 68, 88, 66, 67, 118, 118, + 229, 207, 223, 43, 191, 129, + 46, 182, 152, 168, 144, 51, + 219, 93, 1, 0, 0, 0, 180, 23, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -206,7 +206,7 @@ const BYTE texture_load_depth_float_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h index d73996e19..31ec2d1af 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h @@ -212,10 +212,10 @@ ret const BYTE texture_load_depth_float_scaled_cs[] = { - 68, 88, 66, 67, 97, 66, - 8, 141, 64, 232, 246, 129, - 214, 180, 240, 206, 10, 93, - 136, 7, 1, 0, 0, 0, + 68, 88, 66, 67, 88, 225, + 211, 33, 229, 40, 36, 2, + 174, 238, 58, 147, 100, 14, + 137, 242, 1, 0, 0, 0, 84, 26, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -225,7 +225,7 @@ const BYTE texture_load_depth_float_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h index 1824bb5c2..2aa17af24 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h @@ -171,10 +171,10 @@ ret const BYTE texture_load_depth_unorm_cs[] = { - 68, 88, 66, 67, 69, 6, - 138, 33, 133, 185, 5, 144, - 97, 147, 106, 215, 106, 118, - 65, 58, 1, 0, 0, 0, + 68, 88, 66, 67, 164, 201, + 22, 59, 241, 134, 166, 121, + 89, 49, 109, 127, 19, 134, + 179, 77, 1, 0, 0, 0, 28, 20, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -184,7 +184,7 @@ const BYTE texture_load_depth_unorm_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h index d877269d3..60e54685b 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h @@ -190,10 +190,10 @@ ret const BYTE texture_load_depth_unorm_scaled_cs[] = { - 68, 88, 66, 67, 171, 5, - 112, 51, 93, 95, 86, 30, - 36, 93, 246, 161, 8, 191, - 36, 204, 1, 0, 0, 0, + 68, 88, 66, 67, 46, 48, + 136, 105, 27, 59, 153, 68, + 207, 149, 101, 215, 91, 14, + 213, 200, 1, 0, 0, 0, 188, 22, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -203,7 +203,7 @@ const BYTE texture_load_depth_unorm_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h index 0c1582b51..e2f833cab 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h @@ -756,10 +756,10 @@ ret const BYTE texture_load_dxn_rg8_cs[] = { - 68, 88, 66, 67, 211, 36, - 163, 209, 153, 81, 143, 128, - 61, 32, 177, 173, 61, 97, - 58, 73, 1, 0, 0, 0, + 68, 88, 66, 67, 58, 123, + 85, 153, 121, 158, 245, 188, + 30, 31, 213, 99, 33, 63, + 238, 113, 1, 0, 0, 0, 152, 107, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -769,7 +769,7 @@ const BYTE texture_load_dxn_rg8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h index f19eb9d29..d929471f2 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h @@ -964,10 +964,10 @@ ret const BYTE texture_load_dxt1_rgba8_cs[] = { - 68, 88, 66, 67, 171, 63, - 106, 29, 93, 176, 47, 157, - 131, 34, 243, 102, 115, 232, - 70, 144, 1, 0, 0, 0, + 68, 88, 66, 67, 162, 2, + 233, 77, 119, 170, 48, 9, + 89, 123, 33, 178, 116, 19, + 98, 50, 1, 0, 0, 0, 72, 139, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -977,7 +977,7 @@ const BYTE texture_load_dxt1_rgba8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h index e28a1380c..153919e73 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h @@ -402,10 +402,10 @@ ret const BYTE texture_load_dxt3_rgba8_cs[] = { - 68, 88, 66, 67, 202, 139, - 131, 58, 228, 184, 167, 198, - 214, 82, 38, 18, 195, 26, - 166, 103, 1, 0, 0, 0, + 68, 88, 66, 67, 12, 204, + 97, 23, 183, 245, 147, 165, + 41, 149, 238, 95, 107, 29, + 121, 103, 1, 0, 0, 0, 200, 53, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -415,7 +415,7 @@ const BYTE texture_load_dxt3_rgba8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h index d9525a0e3..a5cb13f4d 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h @@ -223,10 +223,10 @@ ret const BYTE texture_load_dxt3a_cs[] = { - 68, 88, 66, 67, 161, 154, - 167, 17, 42, 20, 207, 220, - 166, 224, 185, 142, 22, 195, - 81, 32, 1, 0, 0, 0, + 68, 88, 66, 67, 104, 192, + 139, 183, 85, 14, 81, 232, + 35, 168, 116, 5, 160, 169, + 85, 249, 1, 0, 0, 0, 208, 28, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -236,7 +236,7 @@ const BYTE texture_load_dxt3a_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h index 70f0637e5..0b2a5e780 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h @@ -388,10 +388,10 @@ ret const BYTE texture_load_dxt3aas1111_cs[] = { - 68, 88, 66, 67, 90, 5, - 35, 3, 92, 51, 204, 73, - 141, 97, 178, 144, 202, 117, - 220, 55, 1, 0, 0, 0, + 68, 88, 66, 67, 22, 23, + 173, 181, 12, 133, 91, 227, + 193, 248, 70, 118, 201, 133, + 160, 27, 1, 0, 0, 0, 116, 60, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -401,7 +401,7 @@ const BYTE texture_load_dxt3aas1111_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h index 4b7c67107..4ed638286 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h @@ -904,10 +904,10 @@ ret const BYTE texture_load_dxt5_rgba8_cs[] = { - 68, 88, 66, 67, 180, 185, - 178, 42, 202, 99, 164, 29, - 112, 142, 14, 240, 160, 77, - 17, 147, 1, 0, 0, 0, + 68, 88, 66, 67, 174, 151, + 189, 10, 239, 215, 42, 88, + 164, 121, 146, 214, 247, 6, + 218, 92, 1, 0, 0, 0, 136, 117, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -917,7 +917,7 @@ const BYTE texture_load_dxt5_rgba8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h index df0266f2c..6f24b0572 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h @@ -820,10 +820,10 @@ ret const BYTE texture_load_dxt5a_r8_cs[] = { - 68, 88, 66, 67, 26, 197, - 196, 184, 97, 248, 148, 119, - 98, 119, 209, 241, 44, 179, - 197, 227, 1, 0, 0, 0, + 68, 88, 66, 67, 254, 188, + 43, 237, 174, 91, 14, 57, + 46, 249, 95, 48, 189, 201, + 171, 161, 1, 0, 0, 0, 36, 112, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -833,7 +833,7 @@ const BYTE texture_load_dxt5a_r8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h index d4719dafd..67c0cbdb1 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h @@ -206,10 +206,10 @@ ret const BYTE texture_load_r10g11b11_rgba16_cs[] = { - 68, 88, 66, 67, 131, 13, - 20, 178, 131, 231, 128, 185, - 113, 12, 55, 205, 96, 44, - 175, 81, 1, 0, 0, 0, + 68, 88, 66, 67, 47, 2, + 160, 5, 228, 91, 168, 34, + 190, 254, 217, 6, 7, 78, + 252, 141, 1, 0, 0, 0, 44, 26, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -219,7 +219,7 @@ const BYTE texture_load_r10g11b11_rgba16_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h index 867dace24..ff438bf21 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h @@ -224,10 +224,10 @@ ret const BYTE texture_load_r10g11b11_rgba16_scaled_cs[] = { - 68, 88, 66, 67, 155, 144, - 74, 111, 245, 166, 226, 11, - 144, 219, 119, 58, 140, 196, - 87, 164, 1, 0, 0, 0, + 68, 88, 66, 67, 20, 16, + 81, 114, 70, 228, 22, 196, + 107, 196, 190, 30, 167, 28, + 162, 144, 1, 0, 0, 0, 176, 28, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -237,7 +237,7 @@ const BYTE texture_load_r10g11b11_rgba16_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h index d0f2a724a..a64921485 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h @@ -316,10 +316,10 @@ ret const BYTE texture_load_r10g11b11_rgba16_snorm_cs[] = { - 68, 88, 66, 67, 132, 107, - 13, 78, 171, 0, 197, 83, - 243, 104, 225, 235, 102, 35, - 191, 255, 1, 0, 0, 0, + 68, 88, 66, 67, 126, 137, + 222, 85, 154, 50, 59, 65, + 64, 122, 77, 236, 149, 56, + 130, 232, 1, 0, 0, 0, 228, 41, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -329,7 +329,7 @@ const BYTE texture_load_r10g11b11_rgba16_snorm_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h index b5fa9cff7..980a7d8bb 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h @@ -334,10 +334,10 @@ ret const BYTE texture_load_r10g11b11_rgba16_snorm_scaled_cs[] = { - 68, 88, 66, 67, 162, 29, - 212, 129, 112, 166, 188, 86, - 123, 71, 28, 10, 208, 33, - 149, 252, 1, 0, 0, 0, + 68, 88, 66, 67, 143, 241, + 241, 106, 117, 162, 243, 107, + 211, 190, 66, 35, 157, 41, + 39, 22, 1, 0, 0, 0, 104, 44, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -347,7 +347,7 @@ const BYTE texture_load_r10g11b11_rgba16_snorm_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h index a9c2bfa67..571407a24 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h @@ -210,10 +210,10 @@ ret const BYTE texture_load_r11g11b10_rgba16_cs[] = { - 68, 88, 66, 67, 140, 202, - 56, 216, 12, 60, 186, 15, - 110, 177, 222, 251, 148, 130, - 188, 179, 1, 0, 0, 0, + 68, 88, 66, 67, 128, 35, + 108, 79, 134, 63, 204, 101, + 37, 250, 141, 229, 110, 97, + 86, 185, 1, 0, 0, 0, 124, 26, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -223,7 +223,7 @@ const BYTE texture_load_r11g11b10_rgba16_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h index dcd872964..dc090002d 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h @@ -228,10 +228,10 @@ ret const BYTE texture_load_r11g11b10_rgba16_scaled_cs[] = { - 68, 88, 66, 67, 137, 198, - 120, 58, 180, 179, 225, 37, - 185, 213, 74, 210, 172, 40, - 217, 34, 1, 0, 0, 0, + 68, 88, 66, 67, 71, 13, + 151, 213, 246, 156, 242, 12, + 33, 146, 244, 98, 204, 37, + 211, 102, 1, 0, 0, 0, 0, 29, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -241,7 +241,7 @@ const BYTE texture_load_r11g11b10_rgba16_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h index 655fc1cc3..41980c994 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h @@ -316,10 +316,10 @@ ret const BYTE texture_load_r11g11b10_rgba16_snorm_cs[] = { - 68, 88, 66, 67, 213, 22, - 164, 196, 90, 153, 244, 222, - 212, 71, 213, 96, 207, 65, - 216, 237, 1, 0, 0, 0, + 68, 88, 66, 67, 148, 131, + 162, 115, 4, 155, 42, 57, + 217, 241, 77, 237, 50, 228, + 133, 33, 1, 0, 0, 0, 228, 41, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -329,7 +329,7 @@ const BYTE texture_load_r11g11b10_rgba16_snorm_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h index 0e333a659..500db9f89 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h @@ -334,10 +334,10 @@ ret const BYTE texture_load_r11g11b10_rgba16_snorm_scaled_cs[] = { - 68, 88, 66, 67, 161, 142, - 120, 161, 78, 207, 43, 55, - 216, 104, 110, 214, 21, 94, - 233, 199, 1, 0, 0, 0, + 68, 88, 66, 67, 75, 177, + 94, 135, 174, 139, 119, 66, + 179, 219, 255, 123, 200, 30, + 105, 239, 1, 0, 0, 0, 104, 44, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -347,7 +347,7 @@ const BYTE texture_load_r11g11b10_rgba16_snorm_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h index 351327ab6..bbdade597 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_r4g4b4a4_b4g4r4a4_cs[] = { - 68, 88, 66, 67, 123, 178, - 4, 149, 160, 65, 196, 92, - 197, 33, 231, 200, 130, 56, - 69, 71, 1, 0, 0, 0, + 68, 88, 66, 67, 49, 31, + 131, 53, 100, 96, 178, 5, + 2, 82, 81, 83, 23, 105, + 45, 74, 1, 0, 0, 0, 28, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_r4g4b4a4_b4g4r4a4_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h index c96fe8c51..7e639b240 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h @@ -177,10 +177,10 @@ ret const BYTE texture_load_r4g4b4a4_b4g4r4a4_scaled_cs[] = { - 68, 88, 66, 67, 217, 199, - 168, 29, 226, 179, 202, 87, - 196, 221, 10, 176, 71, 209, - 93, 59, 1, 0, 0, 0, + 68, 88, 66, 67, 77, 180, + 20, 47, 174, 216, 74, 169, + 81, 35, 81, 193, 58, 15, + 131, 7, 1, 0, 0, 0, 0, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -190,7 +190,7 @@ const BYTE texture_load_r4g4b4a4_b4g4r4a4_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h index ba3b52739..fcd9812cd 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_r5g5b5a1_b5g5r5a1_cs[] = { - 68, 88, 66, 67, 135, 143, - 167, 233, 77, 208, 99, 166, - 216, 43, 121, 223, 203, 20, - 55, 249, 1, 0, 0, 0, + 68, 88, 66, 67, 142, 91, + 118, 66, 49, 193, 130, 167, + 134, 65, 2, 182, 229, 160, + 140, 89, 1, 0, 0, 0, 28, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_r5g5b5a1_b5g5r5a1_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h index 35ef6c89b..12cc39ab1 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h @@ -177,10 +177,10 @@ ret const BYTE texture_load_r5g5b5a1_b5g5r5a1_scaled_cs[] = { - 68, 88, 66, 67, 82, 18, - 33, 217, 174, 124, 154, 217, - 180, 135, 1, 110, 160, 231, - 43, 26, 1, 0, 0, 0, + 68, 88, 66, 67, 118, 127, + 179, 72, 186, 4, 108, 94, + 144, 13, 145, 177, 14, 255, + 152, 175, 1, 0, 0, 0, 0, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -190,7 +190,7 @@ const BYTE texture_load_r5g5b5a1_b5g5r5a1_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h index a6d581bb4..71dfe6ea8 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h @@ -160,10 +160,10 @@ ret const BYTE texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs[] = { - 68, 88, 66, 67, 53, 93, - 80, 84, 203, 45, 115, 170, - 188, 117, 87, 176, 190, 115, - 70, 191, 1, 0, 0, 0, + 68, 88, 66, 67, 242, 245, + 114, 197, 70, 66, 49, 31, + 114, 195, 63, 33, 103, 191, + 133, 52, 1, 0, 0, 0, 148, 18, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -173,7 +173,7 @@ const BYTE texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h index b7ed1f186..30c8a1951 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h @@ -173,10 +173,10 @@ ret const BYTE texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs[] = { - 68, 88, 66, 67, 4, 135, - 9, 244, 156, 123, 41, 147, - 145, 234, 137, 185, 2, 70, - 230, 241, 1, 0, 0, 0, + 68, 88, 66, 67, 224, 225, + 230, 21, 25, 203, 114, 212, + 208, 192, 99, 236, 28, 219, + 255, 255, 1, 0, 0, 0, 120, 20, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -186,7 +186,7 @@ const BYTE texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h index fa0ac7235..279724d2f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_r5g6b5_b5g6r5_cs[] = { - 68, 88, 66, 67, 27, 115, - 39, 235, 56, 147, 179, 61, - 11, 80, 115, 207, 237, 93, - 153, 217, 1, 0, 0, 0, + 68, 88, 66, 67, 127, 73, + 53, 241, 142, 177, 61, 101, + 28, 212, 103, 166, 115, 116, + 219, 222, 1, 0, 0, 0, 28, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_r5g6b5_b5g6r5_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h index 8c6ef5b3e..d9849b0c3 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h @@ -177,10 +177,10 @@ ret const BYTE texture_load_r5g6b5_b5g6r5_scaled_cs[] = { - 68, 88, 66, 67, 188, 32, - 89, 167, 62, 193, 205, 149, - 127, 86, 15, 49, 116, 163, - 146, 187, 1, 0, 0, 0, + 68, 88, 66, 67, 80, 139, + 235, 77, 41, 132, 249, 150, + 54, 120, 97, 180, 209, 107, + 181, 68, 1, 0, 0, 0, 0, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -190,7 +190,7 @@ const BYTE texture_load_r5g6b5_b5g6r5_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.h b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.h new file mode 100644 index 000000000..f9a13bb54 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.h @@ -0,0 +1,92 @@ +// generated from `xb genspirv` +// source: fullscreen_tc.vert +const uint8_t fullscreen_tc_vert[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x76, 0x61, 0x72, 0x5F, 0x74, 0x65, 0x78, 0x63, 0x6F, + 0x6F, 0x72, 0x64, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x67, 0x6C, 0x5F, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x49, 0x6E, 0x64, + 0x65, 0x78, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, + 0x69, 0x6F, 0x6E, 0x00, 0x06, 0x00, 0x07, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, + 0x53, 0x69, 0x7A, 0x65, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0xC4, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x05, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.spv b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.spv new file mode 100644 index 000000000..7e332c65e Binary files /dev/null and b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.spv differ diff --git a/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.txt b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.txt new file mode 100644 index 000000000..5fb049108 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.txt @@ -0,0 +1,66 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 45 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %xe_var_texcoord %gl_VertexIndex %_ + OpSource ESSL 310 + OpName %main "main" + OpName %xe_var_texcoord "xe_var_texcoord" + OpName %gl_VertexIndex "gl_VertexIndex" + OpName %gl_PerVertex "gl_PerVertex" + OpMemberName %gl_PerVertex 0 "gl_Position" + OpMemberName %gl_PerVertex 1 "gl_PointSize" + OpName %_ "" + OpDecorate %xe_var_texcoord Location 0 + OpDecorate %gl_VertexIndex BuiltIn VertexIndex + OpMemberDecorate %gl_PerVertex 0 BuiltIn Position + OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize + OpDecorate %gl_PerVertex Block + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v2float = OpTypeVector %float 2 +%_ptr_Output_v2float = OpTypePointer Output %v2float +%xe_var_texcoord = OpVariable %_ptr_Output_v2float Output + %int = OpTypeInt 32 1 +%_ptr_Input_int = OpTypePointer Input %int +%gl_VertexIndex = OpVariable %_ptr_Input_int Input + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 + %v2uint = OpTypeVector %uint 2 + %uint_2 = OpConstant %uint 2 + %v4float = OpTypeVector %float 4 +%gl_PerVertex = OpTypeStruct %v4float %float +%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex + %_ = OpVariable %_ptr_Output_gl_PerVertex Output + %int_0 = OpConstant %int 0 + %float_2 = OpConstant %float 2 + %float_1 = OpConstant %float 1 + %float_0 = OpConstant %float 0 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %43 = OpConstantComposite %v2uint %uint_2 %uint_2 + %44 = OpConstantComposite %v2float %float_1 %float_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %13 = OpLoad %int %gl_VertexIndex + %15 = OpBitcast %uint %13 + %18 = OpShiftLeftLogical %int %13 %uint_1 + %19 = OpBitcast %uint %18 + %21 = OpCompositeConstruct %v2uint %15 %19 + %24 = OpBitwiseAnd %v2uint %21 %43 + %25 = OpConvertUToF %v2float %24 + OpStore %xe_var_texcoord %25 + %31 = OpLoad %v2float %xe_var_texcoord + %33 = OpVectorTimesScalar %v2float %31 %float_2 + %36 = OpFSub %v2float %33 %44 + %38 = OpCompositeExtract %float %36 0 + %39 = OpCompositeExtract %float %36 1 + %40 = OpCompositeConstruct %v4float %38 %39 %float_0 %float_1 + %42 = OpAccessChain %_ptr_Output_v4float %_ %int_0 + OpStore %42 %40 + OpReturn + OpFunctionEnd diff --git a/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.h b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.h new file mode 100644 index 000000000..614a693a4 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.h @@ -0,0 +1,47 @@ +// generated from `xb genspirv` +// source: uv.frag +const uint8_t uv_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, + 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x76, + 0x61, 0x72, 0x5F, 0x74, 0x65, 0x78, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, + 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.spv b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.spv new file mode 100644 index 000000000..28c041b84 Binary files /dev/null and b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.spv differ diff --git a/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.txt b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.txt new file mode 100644 index 000000000..70e27dfea --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.txt @@ -0,0 +1,37 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 19 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %xe_frag_color %xe_var_texcoord + OpExecutionMode %main OriginUpperLeft + OpSource ESSL 310 + OpName %main "main" + OpName %xe_frag_color "xe_frag_color" + OpName %xe_var_texcoord "xe_var_texcoord" + OpDecorate %xe_frag_color RelaxedPrecision + OpDecorate %xe_frag_color Location 0 + OpDecorate %xe_var_texcoord Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output + %v2float = OpTypeVector %float 2 +%_ptr_Input_v2float = OpTypePointer Input %v2float +%xe_var_texcoord = OpVariable %_ptr_Input_v2float Input + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 + %main = OpFunction %void None %3 + %5 = OpLabel + %13 = OpLoad %v2float %xe_var_texcoord + %16 = OpCompositeExtract %float %13 0 + %17 = OpCompositeExtract %float %13 1 + %18 = OpCompositeConstruct %v4float %16 %17 %float_0 %float_1 + OpStore %xe_frag_color %18 + OpReturn + OpFunctionEnd diff --git a/src/xenia/gpu/shaders/fullscreen.vs.hlsl b/src/xenia/gpu/shaders/fullscreen.vs.hlsl new file mode 100644 index 000000000..3314d1d87 --- /dev/null +++ b/src/xenia/gpu/shaders/fullscreen.vs.hlsl @@ -0,0 +1,5 @@ +// A triangle covering the whole viewport. +float4 main(uint xe_vertex_id : SV_VertexID) : SV_Position { + return float4(((xe_vertex_id.xx >> uint2(0u, 1u)) & 1u) * 4.0 - 1.0, 0.0, + 1.0); +} diff --git a/src/xenia/gpu/shaders/fullscreen_tc.vert b/src/xenia/gpu/shaders/fullscreen_tc.vert new file mode 100644 index 000000000..340091ac3 --- /dev/null +++ b/src/xenia/gpu/shaders/fullscreen_tc.vert @@ -0,0 +1,10 @@ +#version 310 es + +// A triangle covering the whole viewport. + +layout(location = 0) out vec2 xe_var_texcoord; + +void main() { + xe_var_texcoord = vec2(uvec2(gl_VertexIndex, gl_VertexIndex << 1u) & 2u); + gl_Position = vec4(xe_var_texcoord * 2.0 - 1.0, 0.0, 1.0); +} diff --git a/src/xenia/gpu/shaders/fullscreen_tc.vs.hlsl b/src/xenia/gpu/shaders/fullscreen_tc.vs.hlsl deleted file mode 100644 index e862f0b7c..000000000 --- a/src/xenia/gpu/shaders/fullscreen_tc.vs.hlsl +++ /dev/null @@ -1,7 +0,0 @@ -// A triangle covering the whole viewport. -void main(uint xe_vertex_id : SV_VertexID, out float2 xe_texcoord : TEXCOORD, - out float4 xe_position : SV_Position) { - xe_texcoord = float2(uint2(xe_vertex_id, xe_vertex_id << 1u) & 2u); - xe_position = - float4(xe_texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); -} diff --git a/src/xenia/gpu/shaders/fxaa.cs.hlsl b/src/xenia/gpu/shaders/fxaa.cs.hlsl new file mode 100644 index 000000000..74a9032bb --- /dev/null +++ b/src/xenia/gpu/shaders/fxaa.cs.hlsl @@ -0,0 +1,5 @@ +#define FXAA_QUALITY__PRESET 12 +#define FXAA_QUALITY__SUBPIX 0.75 +#define FXAA_QUALITY__EDGE_THRESHOLD 0.166 +#define FXAA_QUALITY__EDGE_THRESHOLD_MIN 0.0833 +#include "fxaa.hlsli" diff --git a/src/xenia/gpu/shaders/fxaa.hlsli b/src/xenia/gpu/shaders/fxaa.hlsli new file mode 100644 index 000000000..f20fdd4a5 --- /dev/null +++ b/src/xenia/gpu/shaders/fxaa.hlsli @@ -0,0 +1,48 @@ +// Inputs: +// - FXAA_QUALITY__PRESET +// - FXAA_QUALITY__SUBPIX +// - FXAA_QUALITY__EDGE_THRESHOLD +// - FXAA_QUALITY__EDGE_THRESHOLD_MIN + +// "use of potentially uninitialized variable" in FxaaPixelShader due to the +// early exit with a `return` in the beginning of the function, caused by a bug +// in FXC (the warning is common for early exiting in HLSL in general). +#pragma warning(disable: 4000) + +cbuffer XeApplyGammaRampConstants : register(b0) { + uint2 xe_fxaa_size; + float2 xe_fxaa_size_inv; +}; + +RWTexture2D xe_fxaa_dest : register(u0); +Texture2D xe_fxaa_source : register(t0); +SamplerState xe_sampler_linear_clamp : register(s0); + +#define FXAA_PC 1 +#define FXAA_HLSL_5 1 +#include "../../../../third_party/fxaa/FXAA3_11.h" + +[numthreads(8, 8, 1)] +void main(uint3 xe_thread_id : SV_DispatchThreadID) { + [branch] if (any(xe_thread_id.xy >= xe_fxaa_size)) { + return; + } + FxaaTex fxaa_texture; + fxaa_texture.smpl = xe_sampler_linear_clamp; + fxaa_texture.tex = xe_fxaa_source; + // Force alpha to 1 to simplify calculations, won't need it anymore anyway. + xe_fxaa_dest[xe_thread_id.xy] = + float4( + FxaaPixelShader( + (float2(xe_thread_id.xy) + 0.5) * xe_fxaa_size_inv, + (float2(xe_thread_id.xy).xyxy + float2(0.0, 1.0).xxyy) * + xe_fxaa_size_inv.xyxy, + fxaa_texture, fxaa_texture, fxaa_texture, xe_fxaa_size_inv, + float2(-0.5, 0.5).xxyy * xe_fxaa_size_inv.xyxy, + float2(-2.0, 2.0).xxyy * xe_fxaa_size_inv.xyxy, + float2(8.0, -4.0).xxyy * xe_fxaa_size_inv.xyxy, + FXAA_QUALITY__SUBPIX, FXAA_QUALITY__EDGE_THRESHOLD, + FXAA_QUALITY__EDGE_THRESHOLD_MIN, 8.0, 0.125, 0.05, + float4(1.0, -1.0, 0.25, -0.25)).rgb, + 1.0); +} diff --git a/src/xenia/gpu/shaders/fxaa_extreme.cs.hlsl b/src/xenia/gpu/shaders/fxaa_extreme.cs.hlsl new file mode 100644 index 000000000..68eb85b96 --- /dev/null +++ b/src/xenia/gpu/shaders/fxaa_extreme.cs.hlsl @@ -0,0 +1,5 @@ +#define FXAA_QUALITY__PRESET 39 +#define FXAA_QUALITY__SUBPIX 1.0 +#define FXAA_QUALITY__EDGE_THRESHOLD 0.063 +#define FXAA_QUALITY__EDGE_THRESHOLD_MIN 0.0312 +#include "fxaa.hlsli" diff --git a/src/xenia/gpu/shaders/stretch.ps.hlsl b/src/xenia/gpu/shaders/stretch.ps.hlsl deleted file mode 100644 index c7a568434..000000000 --- a/src/xenia/gpu/shaders/stretch.ps.hlsl +++ /dev/null @@ -1,8 +0,0 @@ -Texture2D xe_texture : register(t0); -SamplerState xe_sampler_linear_clamp : register(s0); - -float4 main(float2 xe_texcoord : TEXCOORD) : SV_Target { - // Force alpha to 1 to make sure the surface won't be translucent. - return float4( - xe_texture.SampleLevel(xe_sampler_linear_clamp, xe_texcoord, 0.0f), 1.0f); -} diff --git a/src/xenia/gpu/shaders/stretch_gamma.ps.hlsl b/src/xenia/gpu/shaders/stretch_gamma.ps.hlsl deleted file mode 100644 index a13e333a8..000000000 --- a/src/xenia/gpu/shaders/stretch_gamma.ps.hlsl +++ /dev/null @@ -1,20 +0,0 @@ -Texture2D xe_texture : register(t0); -Texture1D xe_gamma_ramp : register(t1); -SamplerState xe_sampler_linear_clamp : register(s0); -cbuffer XeStretchGammaRootConstants : register(b0) { - float xe_gamma_ramp_inv_size; -}; - -float4 main(float2 xe_texcoord : TEXCOORD) : SV_Target { - float3 color = - xe_texture.SampleLevel(xe_sampler_linear_clamp, xe_texcoord, 0.0f); - // The center of the first texel of the LUT contains the value for 0, and the - // center of the last texel contains the value for 1. - color = - color * (1.0f - xe_gamma_ramp_inv_size) + (0.5 * xe_gamma_ramp_inv_size); - color.r = xe_gamma_ramp.SampleLevel(xe_sampler_linear_clamp, color.r, 0.0f).r; - color.g = xe_gamma_ramp.SampleLevel(xe_sampler_linear_clamp, color.g, 0.0f).g; - color.b = xe_gamma_ramp.SampleLevel(xe_sampler_linear_clamp, color.b, 0.0f).b; - // Force alpha to 1 to make sure the surface won't be translucent. - return float4(color, 1.0f); -} diff --git a/src/xenia/gpu/shaders/texture_load_32bpb.cs.hlsl b/src/xenia/gpu/shaders/texture_load_32bpb.cs.hlsl new file mode 100644 index 000000000..4ea67a248 --- /dev/null +++ b/src/xenia/gpu/shaders/texture_load_32bpb.cs.hlsl @@ -0,0 +1,2 @@ +#define XE_TEXTURE_LOAD_32BPB_TRANSFORM(blocks) (blocks) +#include "texture_load_32bpb.hlsli" diff --git a/src/xenia/gpu/shaders/uv.frag b/src/xenia/gpu/shaders/uv.frag new file mode 100644 index 000000000..03eaef5ce --- /dev/null +++ b/src/xenia/gpu/shaders/uv.frag @@ -0,0 +1,10 @@ +#version 310 es +precision highp float; + +layout(location = 0) in vec2 xe_var_texcoord; + +layout(location = 0) out lowp vec4 xe_frag_color; + +void main() { + xe_frag_color = vec4(xe_var_texcoord, 0.0, 1.0); +} diff --git a/src/xenia/gpu/trace_dump.cc b/src/xenia/gpu/trace_dump.cc index a78964d14..2932a4110 100644 --- a/src/xenia/gpu/trace_dump.cc +++ b/src/xenia/gpu/trace_dump.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,6 +18,7 @@ #include "xenia/gpu/graphics_system.h" #include "xenia/memory.h" #include "xenia/ui/file_picker.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" #include "xenia/xbox.h" @@ -94,7 +95,8 @@ bool TraceDump::Setup() { // Create the emulator but don't initialize so we can setup the window. emulator_ = std::make_unique("", "", "", ""); X_STATUS result = emulator_->Setup( - nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr); + nullptr, nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, + nullptr); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result); return false; @@ -125,18 +127,19 @@ int TraceDump::Run() { // Capture. int result = 0; - auto raw_image = graphics_system_->Capture(); - if (raw_image) { + ui::Presenter* presenter = graphics_system_->presenter(); + ui::RawImage raw_image; + if (presenter && presenter->CaptureGuestOutput(raw_image)) { // Save framebuffer png. auto png_path = base_output_path_.replace_extension(".png"); auto handle = filesystem::OpenFile(png_path, "wb"); auto callback = [](void* context, void* data, int size) { fwrite(data, 1, size, (FILE*)context); }; - stbi_write_png_to_func(callback, handle, static_cast(raw_image->width), - static_cast(raw_image->height), 4, - raw_image->data.data(), - static_cast(raw_image->stride)); + stbi_write_png_to_func(callback, handle, static_cast(raw_image.width), + static_cast(raw_image.height), 4, + raw_image.data.data(), + static_cast(raw_image.stride)); fclose(handle); } else { result = 1; diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index 8f2c98b8a..54db1156c 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -87,15 +87,19 @@ void TracePlayer::PlayTrace(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, bool clear_caches) { playing_trace_ = true; + // Pass a copy of present_last_copy_ to the thread so it's not accessible by + // multiple threads at once. + bool present_last_copy = present_last_copy_; graphics_system_->command_processor()->CallInThread([=]() { - PlayTraceOnThread(trace_data, trace_size, playback_mode, clear_caches); + PlayTraceOnThread(trace_data, trace_size, playback_mode, clear_caches, + present_last_copy); }); } void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, - bool clear_caches) { + bool clear_caches, bool present_last_copy) { auto memory = graphics_system_->memory(); auto command_processor = graphics_system_->command_processor(); @@ -103,7 +107,10 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, command_processor->ClearCaches(); } - command_processor->set_swap_mode(SwapMode::kIgnored); + if (present_last_copy) { + command_processor->SetIgnoreSwap(true); + } + playback_percent_ = 0; auto trace_end = trace_data + trace_size; @@ -215,8 +222,11 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, } playing_trace_ = false; - command_processor->set_swap_mode(SwapMode::kNormal); - command_processor->IssueSwap(0, 1280, 720); + + if (present_last_copy) { + command_processor->SetIgnoreSwap(false); + command_processor->IssueSwap(0, 1280, 720); + } playback_event_->Set(); } diff --git a/src/xenia/gpu/trace_player.h b/src/xenia/gpu/trace_player.h index d56205d59..cfc2702a1 100644 --- a/src/xenia/gpu/trace_player.h +++ b/src/xenia/gpu/trace_player.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -33,6 +33,9 @@ class TracePlayer : public TraceReader { ~TracePlayer() override; GraphicsSystem* graphics_system() const { return graphics_system_; } + void SetPresentLastCopy(bool present_last_copy) { + present_last_copy_ = present_last_copy; + } int current_frame_index() const { return current_frame_index_; } int current_command_index() const { return current_command_index_; } bool is_playing_trace() const { return playing_trace_; } @@ -51,9 +54,13 @@ class TracePlayer : public TraceReader { void PlayTrace(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, bool clear_caches); void PlayTraceOnThread(const uint8_t* trace_data, size_t trace_size, - TracePlaybackMode playback_mode, bool clear_caches); + TracePlaybackMode playback_mode, bool clear_caches, + bool present_last_copy); GraphicsSystem* graphics_system_; + // Whether to present the results of the latest resolve instead of displaying + // the front buffer from the trace. + bool present_last_copy_ = false; int current_frame_index_; int current_command_index_; bool playing_trace_ = false; diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index d5f389276..660f24805 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -30,6 +30,9 @@ #include "xenia/memory.h" #include "xenia/ui/file_picker.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" @@ -51,7 +54,8 @@ static const ImVec4 kColorIgnored = TraceViewer::TraceViewer(xe::ui::WindowedAppContext& app_context, const std::string_view name) - : xe::ui::WindowedApp(app_context, name, "some.trace") { + : xe::ui::WindowedApp(app_context, name, "some.trace"), + window_listener_(*this) { AddPositionalOption("target_trace_file"); } @@ -102,22 +106,27 @@ bool TraceViewer::OnInitialize() { } bool TraceViewer::Setup() { + enum : size_t { + kZOrderImGui, + kZOrderTraceViewerInput, + }; + // Main display window. assert_true(app_context().IsInUIThread()); - window_ = xe::ui::Window::Create(app_context(), "xenia-gpu-trace-viewer"); - if (!window_->Initialize()) { - XELOGE("Failed to initialize main window"); + window_ = xe::ui::Window::Create(app_context(), "xenia-gpu-trace-viewer", + 1920, 1200); + window_->AddListener(&window_listener_); + window_->AddInputListener(&window_listener_, kZOrderTraceViewerInput); + if (!window_->Open()) { + XELOGE("Failed to open the main window"); return false; } - window_->on_closed.AddListener( - [this](xe::ui::UIEvent* e) { app_context().QuitFromUIThread(); }); - window_->Resize(1920, 1200); // Create the emulator but don't initialize so we can setup the window. emulator_ = std::make_unique("", "", "", ""); X_STATUS result = emulator_->Setup( - window_.get(), nullptr, [this]() { return CreateGraphicsSystem(); }, - nullptr); + window_.get(), nullptr, nullptr, + [this]() { return CreateGraphicsSystem(); }, nullptr); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result); return false; @@ -125,31 +134,55 @@ bool TraceViewer::Setup() { memory_ = emulator_->memory(); graphics_system_ = emulator_->graphics_system(); - window_->set_imgui_input_enabled(true); - - window_->on_key_char.AddListener([&](xe::ui::KeyEvent* e) { - if (e->virtual_key() == xe::ui::VirtualKey::kF5) { - graphics_system_->ClearCaches(); - e->set_handled(true); - } - }); - player_ = std::make_unique(graphics_system_); + player_->SetPresentLastCopy(true); - window_->on_painting.AddListener([this](xe::ui::UIEvent* e) { - DrawUI(); - - // Continuous paint. - window_->Invalidate(); - }); - window_->Invalidate(); + // Setup drawing to the window. + xe::ui::GraphicsProvider& graphics_provider = *graphics_system_->provider(); + presenter_ = graphics_provider.CreatePresenter(); + if (!presenter_) { + XELOGE("Failed to initialize the presenter"); + return false; + } + immediate_drawer_ = graphics_provider.CreateImmediateDrawer(); + if (!immediate_drawer_) { + XELOGE("Failed to initialize the immediate drawer"); + return false; + } + immediate_drawer_->SetPresenter(presenter_.get()); + imgui_drawer_ = + std::make_unique(window_.get(), kZOrderImGui); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + immediate_drawer_.get()); + trace_viewer_dialog_ = std::unique_ptr( + new TraceViewerDialog(imgui_drawer_.get(), *this)); + window_->SetPresenter(presenter_.get()); return true; } +void TraceViewer::TraceViewerWindowListener::OnClosing(xe::ui::UIEvent& e) { + trace_viewer_.app_context().QuitFromUIThread(); +} + +void TraceViewer::TraceViewerWindowListener::OnKeyDown(xe::ui::KeyEvent& e) { + switch (e.virtual_key()) { + case xe::ui::VirtualKey::kF5: + trace_viewer_.graphics_system_->ClearCaches(); + break; + default: + return; + } + e.set_handled(true); +} + +void TraceViewer::TraceViewerDialog::OnDraw(ImGuiIO& io) { + trace_viewer_.DrawUI(); +} + bool TraceViewer::Load(const std::filesystem::path& trace_file_path) { auto file_name = trace_file_path.filename(); - window_->set_title("Xenia GPU Trace Viewer: " + xe::path_to_utf8(file_name)); + window_->SetTitle("Xenia GPU Trace Viewer: " + xe::path_to_utf8(file_name)); if (!player_->Open(trace_file_path)) { XELOGE("Could not load trace file"); @@ -233,8 +266,9 @@ void TraceViewer::DrawControllerUI() { void TraceViewer::DrawPacketDisassemblerUI() { ImGui::SetNextWindowCollapsed(true, ImGuiCond_FirstUseEver); - ImGui::SetNextWindowPos(ImVec2(float(window_->width()) - 500 - 5, 5), - ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos( + ImVec2(float(window_->GetActualLogicalWidth()) - 500 - 5, 5), + ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(500, 300)); if (!ImGui::Begin("Packet Disassembler", nullptr)) { ImGui::End(); @@ -1052,8 +1086,9 @@ void TraceViewer::DrawStateUI() { auto command_processor = graphics_system_->command_processor(); auto& regs = *graphics_system_->register_file(); - ImGui::SetNextWindowPos(ImVec2(float(window_->width()) - 500 - 5, 30), - ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos( + ImVec2(float(window_->GetActualLogicalWidth()) - 500 - 5, 30), + ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(500, 680)); if (!ImGui::Begin("State", nullptr)) { ImGui::End(); diff --git a/src/xenia/gpu/trace_viewer.h b/src/xenia/gpu/trace_viewer.h index 1e22439fb..ecca12792 100644 --- a/src/xenia/gpu/trace_viewer.h +++ b/src/xenia/gpu/trace_viewer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,7 +18,12 @@ #include "xenia/gpu/trace_protocol.h" #include "xenia/gpu/xenos.h" #include "xenia/memory.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" namespace xe { @@ -38,6 +43,7 @@ class TraceViewer : public xe::ui::WindowedApp { const std::string_view name); virtual std::unique_ptr CreateGraphicsSystem() = 0; + GraphicsSystem* graphics_system() const { return graphics_system_; } void DrawMultilineString(const std::string_view str); @@ -56,13 +62,34 @@ class TraceViewer : public xe::ui::WindowedApp { virtual bool Setup(); - std::unique_ptr window_; - std::unique_ptr emulator_; - Memory* memory_ = nullptr; - GraphicsSystem* graphics_system_ = nullptr; - std::unique_ptr player_; - private: + class TraceViewerWindowListener final : public xe::ui::WindowListener, + public xe::ui::WindowInputListener { + public: + explicit TraceViewerWindowListener(TraceViewer& trace_viewer) + : trace_viewer_(trace_viewer) {} + + void OnClosing(xe::ui::UIEvent& e) override; + + void OnKeyDown(xe::ui::KeyEvent& e) override; + + private: + TraceViewer& trace_viewer_; + }; + + class TraceViewerDialog final : public ui::ImGuiDialog { + public: + explicit TraceViewerDialog(xe::ui::ImGuiDrawer* imgui_drawer, + TraceViewer& trace_viewer) + : xe::ui::ImGuiDialog(imgui_drawer), trace_viewer_(trace_viewer) {} + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + TraceViewer& trace_viewer_; + }; + enum class ShaderDisplayType : int { kUcode, kTranslated, @@ -92,6 +119,20 @@ class TraceViewer : public xe::ui::WindowedApp { void DrawVertexFetcher(Shader* shader, const Shader::VertexBinding& vertex_binding, const xenos::xe_gpu_vertex_fetch_t* fetch); + + TraceViewerWindowListener window_listener_; + + std::unique_ptr window_; + + std::unique_ptr emulator_; + Memory* memory_ = nullptr; + GraphicsSystem* graphics_system_ = nullptr; + std::unique_ptr player_; + + std::unique_ptr presenter_; + std::unique_ptr immediate_drawer_; + std::unique_ptr imgui_drawer_; + std::unique_ptr trace_viewer_dialog_; }; } // namespace gpu diff --git a/src/xenia/gpu/ucode.h b/src/xenia/gpu/ucode.h index 798fd5367..e86387535 100644 --- a/src/xenia/gpu/ucode.h +++ b/src/xenia/gpu/ucode.h @@ -599,6 +599,8 @@ struct alignas(uint32_t) VertexFetchInstruction { // Required condition value of the comparision (true or false). bool predicate_condition() const { return data_.pred_condition == 1; } // Vertex fetch constant index [0-95]. + // Applicable only to vfetch_full (the address from vfetch_full is reused in + // vfetch_mini). uint32_t fetch_constant_index() const { return data_.const_index * 3 + data_.const_index_sel; } @@ -606,6 +608,8 @@ struct alignas(uint32_t) VertexFetchInstruction { uint32_t dest() const { return data_.dst_reg; } uint32_t dest_swizzle() const { return data_.dst_swiz; } bool is_dest_relative() const { return data_.dst_reg_am; } + // The source is applicable only to vfetch_full (the address from vfetch_full + // is reused in vfetch_mini). uint32_t src() const { return data_.src_reg; } uint32_t src_swizzle() const { return data_.src_swiz; } bool is_src_relative() const { return data_.src_reg_am; } @@ -644,18 +648,21 @@ struct alignas(uint32_t) VertexFetchInstruction { xenos::SignedRepeatingFractionMode signed_rf_mode() const { return data_.signed_rf_mode_all; } + // If true, the floating-point index is rounded to the nearest integer (likely + // as floor(index + 0.5) because rounding to the nearest even makes no sense + // for addressing, both 1.5 and 2.5 would be 2). + // Otherwise, it's floored (rounded towards negative infinity). + // Applicable only to vfetch_full (the address from vfetch_full is reused in + // vfetch_mini). + // http://web.archive.org/web/20090914055358/http://msdn.microsoft.com/en-us/library/bb313960.aspx bool is_index_rounded() const { return data_.is_index_rounded == 1; } // Dword stride, [0, 255]. + // Applicable only to vfetch_full (the address from vfetch_full is reused in + // vfetch_mini). uint32_t stride() const { return data_.stride; } // Dword offset, [-4194304, 4194303]. int32_t offset() const { return data_.offset; } - void AssignFromFull(const VertexFetchInstruction& full) { - data_.stride = full.data_.stride; - data_.const_index = full.data_.const_index; - data_.const_index_sel = full.data_.const_index_sel; - } - private: struct Data { struct { diff --git a/src/xenia/gpu/vulkan/deferred_command_buffer.cc b/src/xenia/gpu/vulkan/deferred_command_buffer.cc index 641843fc9..efb34d252 100644 --- a/src/xenia/gpu/vulkan/deferred_command_buffer.cc +++ b/src/xenia/gpu/vulkan/deferred_command_buffer.cc @@ -36,7 +36,7 @@ void DeferredCommandBuffer::Execute(VkCommandBuffer command_buffer) { #endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = - command_processor_.GetVulkanContext().GetVulkanProvider().dfn(); + command_processor_.GetVulkanProvider().dfn(); const uintmax_t* stream = command_stream_.data(); size_t stream_remaining = command_stream_.size(); while (stream_remaining) { diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.cc b/src/xenia/gpu/vulkan/vulkan_command_processor.cc index dfebc901a..5c8a713db 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.cc +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.cc @@ -29,7 +29,7 @@ #include "xenia/gpu/vulkan/vulkan_shader.h" #include "xenia/gpu/vulkan/vulkan_shared_memory.h" #include "xenia/gpu/xenos.h" -#include "xenia/ui/vulkan/vulkan_context.h" +#include "xenia/ui/vulkan/vulkan_presenter.h" #include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/vulkan/vulkan_util.h" @@ -37,6 +37,12 @@ namespace xe { namespace gpu { namespace vulkan { +// Generated with `xb buildshaders`. +namespace shaders { +#include "xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_tc_vert.h" +#include "xenia/gpu/shaders/bytecode/vulkan_spirv/uv_frag.h" +} // namespace shaders + VulkanCommandProcessor::VulkanCommandProcessor( VulkanGraphicsSystem* graphics_system, kernel::KernelState* kernel_state) : CommandProcessor(graphics_system, kernel_state), @@ -58,8 +64,7 @@ bool VulkanCommandProcessor::SetupContext() { return false; } - const ui::vulkan::VulkanProvider& provider = - GetVulkanContext().GetVulkanProvider(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -274,6 +279,215 @@ bool VulkanCommandProcessor::SetupContext() { // interlocks case. dfn.vkUpdateDescriptorSets(device, 1, write_descriptor_sets, 0, nullptr); + // Swap objects. + + // Swap render pass. Doesn't make assumptions about outer usage (explicit + // barriers must be used instead) for simplicity of use in different scenarios + // with different pipelines. + VkAttachmentDescription swap_render_pass_attachment; + swap_render_pass_attachment.flags = 0; + swap_render_pass_attachment.format = + ui::vulkan::VulkanPresenter::kGuestOutputFormat; + swap_render_pass_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + swap_render_pass_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + swap_render_pass_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + swap_render_pass_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + swap_render_pass_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + swap_render_pass_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + swap_render_pass_attachment.finalLayout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentReference swap_render_pass_color_attachment; + swap_render_pass_color_attachment.attachment = 0; + swap_render_pass_color_attachment.layout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkSubpassDescription swap_render_pass_subpass = {}; + swap_render_pass_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + swap_render_pass_subpass.colorAttachmentCount = 1; + swap_render_pass_subpass.pColorAttachments = + &swap_render_pass_color_attachment; + VkSubpassDependency swap_render_pass_dependencies[2]; + for (uint32_t i = 0; i < 2; ++i) { + VkSubpassDependency& swap_render_pass_dependency = + swap_render_pass_dependencies[i]; + swap_render_pass_dependency.srcSubpass = i ? 0 : VK_SUBPASS_EXTERNAL; + swap_render_pass_dependency.dstSubpass = i ? VK_SUBPASS_EXTERNAL : 0; + swap_render_pass_dependency.srcStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + swap_render_pass_dependency.dstStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + swap_render_pass_dependency.srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + swap_render_pass_dependency.dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + swap_render_pass_dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + } + VkRenderPassCreateInfo swap_render_pass_create_info; + swap_render_pass_create_info.sType = + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + swap_render_pass_create_info.pNext = nullptr; + swap_render_pass_create_info.flags = 0; + swap_render_pass_create_info.attachmentCount = 1; + swap_render_pass_create_info.pAttachments = &swap_render_pass_attachment; + swap_render_pass_create_info.subpassCount = 1; + swap_render_pass_create_info.pSubpasses = &swap_render_pass_subpass; + swap_render_pass_create_info.dependencyCount = + uint32_t(xe::countof(swap_render_pass_dependencies)); + swap_render_pass_create_info.pDependencies = swap_render_pass_dependencies; + if (dfn.vkCreateRenderPass(device, &swap_render_pass_create_info, nullptr, + &swap_render_pass_) != VK_SUCCESS) { + XELOGE("Failed to create the Vulkan render pass for presentation"); + return false; + } + + // Swap pipeline layout. + // TODO(Triang3l): Source binding, push constants, FXAA pipeline layout. + VkPipelineLayoutCreateInfo swap_pipeline_layout_create_info; + swap_pipeline_layout_create_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + swap_pipeline_layout_create_info.pNext = nullptr; + swap_pipeline_layout_create_info.flags = 0; + swap_pipeline_layout_create_info.setLayoutCount = 0; + swap_pipeline_layout_create_info.pSetLayouts = nullptr; + swap_pipeline_layout_create_info.pushConstantRangeCount = 0; + swap_pipeline_layout_create_info.pPushConstantRanges = nullptr; + if (dfn.vkCreatePipelineLayout(device, &swap_pipeline_layout_create_info, + nullptr, + &swap_pipeline_layout_) != VK_SUCCESS) { + XELOGE("Failed to create the Vulkan pipeline layout for presentation"); + return false; + } + + // Swap pipeline. + + VkPipelineShaderStageCreateInfo swap_pipeline_stages[2]; + swap_pipeline_stages[0].sType = + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + swap_pipeline_stages[0].pNext = nullptr; + swap_pipeline_stages[0].flags = 0; + swap_pipeline_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + swap_pipeline_stages[0].module = ui::vulkan::util::CreateShaderModule( + provider, shaders::fullscreen_tc_vert, + sizeof(shaders::fullscreen_tc_vert)); + if (swap_pipeline_stages[0].module == VK_NULL_HANDLE) { + XELOGE("Failed to create the Vulkan vertex shader module for presentation"); + return false; + } + swap_pipeline_stages[0].pName = "main"; + swap_pipeline_stages[0].pSpecializationInfo = nullptr; + swap_pipeline_stages[1].sType = + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + swap_pipeline_stages[1].pNext = nullptr; + swap_pipeline_stages[1].flags = 0; + swap_pipeline_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + swap_pipeline_stages[1].module = ui::vulkan::util::CreateShaderModule( + provider, shaders::uv_frag, sizeof(shaders::uv_frag)); + if (swap_pipeline_stages[1].module == VK_NULL_HANDLE) { + XELOGE( + "Failed to create the Vulkan fragment shader module for presentation"); + dfn.vkDestroyShaderModule(device, swap_pipeline_stages[0].module, nullptr); + return false; + } + swap_pipeline_stages[1].pName = "main"; + swap_pipeline_stages[1].pSpecializationInfo = nullptr; + + VkPipelineVertexInputStateCreateInfo swap_pipeline_vertex_input_state = {}; + swap_pipeline_vertex_input_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + + VkPipelineInputAssemblyStateCreateInfo swap_pipeline_input_assembly_state; + swap_pipeline_input_assembly_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + swap_pipeline_input_assembly_state.pNext = nullptr; + swap_pipeline_input_assembly_state.flags = 0; + swap_pipeline_input_assembly_state.topology = + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + swap_pipeline_input_assembly_state.primitiveRestartEnable = VK_FALSE; + + VkPipelineViewportStateCreateInfo swap_pipeline_viewport_state; + swap_pipeline_viewport_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + swap_pipeline_viewport_state.pNext = nullptr; + swap_pipeline_viewport_state.flags = 0; + swap_pipeline_viewport_state.viewportCount = 1; + swap_pipeline_viewport_state.pViewports = nullptr; + swap_pipeline_viewport_state.scissorCount = 1; + swap_pipeline_viewport_state.pScissors = nullptr; + + VkPipelineRasterizationStateCreateInfo swap_pipeline_rasterization_state = {}; + swap_pipeline_rasterization_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + swap_pipeline_rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; + swap_pipeline_rasterization_state.cullMode = VK_CULL_MODE_NONE; + swap_pipeline_rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + swap_pipeline_rasterization_state.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo swap_pipeline_multisample_state = {}; + swap_pipeline_multisample_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + swap_pipeline_multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState + swap_pipeline_color_blend_attachment_state = {}; + swap_pipeline_color_blend_attachment_state.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + VkPipelineColorBlendStateCreateInfo swap_pipeline_color_blend_state = {}; + swap_pipeline_color_blend_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + swap_pipeline_color_blend_state.attachmentCount = 1; + swap_pipeline_color_blend_state.pAttachments = + &swap_pipeline_color_blend_attachment_state; + + static const VkDynamicState kSwapPipelineDynamicStates[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + VkPipelineDynamicStateCreateInfo swap_pipeline_dynamic_state; + swap_pipeline_dynamic_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + swap_pipeline_dynamic_state.pNext = nullptr; + swap_pipeline_dynamic_state.flags = 0; + swap_pipeline_dynamic_state.dynamicStateCount = + uint32_t(xe::countof(kSwapPipelineDynamicStates)); + swap_pipeline_dynamic_state.pDynamicStates = kSwapPipelineDynamicStates; + + VkGraphicsPipelineCreateInfo swap_pipeline_create_info; + swap_pipeline_create_info.sType = + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + swap_pipeline_create_info.pNext = nullptr; + swap_pipeline_create_info.flags = 0; + swap_pipeline_create_info.stageCount = + uint32_t(xe::countof(swap_pipeline_stages)); + swap_pipeline_create_info.pStages = swap_pipeline_stages; + swap_pipeline_create_info.pVertexInputState = + &swap_pipeline_vertex_input_state; + swap_pipeline_create_info.pInputAssemblyState = + &swap_pipeline_input_assembly_state; + swap_pipeline_create_info.pTessellationState = nullptr; + swap_pipeline_create_info.pViewportState = &swap_pipeline_viewport_state; + swap_pipeline_create_info.pRasterizationState = + &swap_pipeline_rasterization_state; + swap_pipeline_create_info.pMultisampleState = + &swap_pipeline_multisample_state; + swap_pipeline_create_info.pDepthStencilState = nullptr; + swap_pipeline_create_info.pColorBlendState = &swap_pipeline_color_blend_state; + swap_pipeline_create_info.pDynamicState = &swap_pipeline_dynamic_state; + swap_pipeline_create_info.layout = swap_pipeline_layout_; + swap_pipeline_create_info.renderPass = swap_render_pass_; + swap_pipeline_create_info.subpass = 0; + swap_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; + swap_pipeline_create_info.basePipelineIndex = UINT32_MAX; + VkResult swap_pipeline_create_result = dfn.vkCreateGraphicsPipelines( + device, VK_NULL_HANDLE, 1, &swap_pipeline_create_info, nullptr, + &swap_pipeline_); + for (size_t i = 0; i < xe::countof(swap_pipeline_stages); ++i) { + dfn.vkDestroyShaderModule(device, swap_pipeline_stages[i].module, nullptr); + } + if (swap_pipeline_create_result != VK_SUCCESS) { + XELOGE("Failed to create the Vulkan pipeline for presentation"); + return false; + } + // Just not to expose uninitialized memory. std::memset(&system_constants_, 0, sizeof(system_constants_)); @@ -283,11 +497,26 @@ bool VulkanCommandProcessor::SetupContext() { void VulkanCommandProcessor::ShutdownContext() { AwaitAllQueueOperationsCompletion(); - const ui::vulkan::VulkanProvider& provider = - GetVulkanContext().GetVulkanProvider(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); + for (const auto& framebuffer_pair : swap_framebuffers_outdated_) { + dfn.vkDestroyFramebuffer(device, framebuffer_pair.second, nullptr); + } + swap_framebuffers_outdated_.clear(); + for (SwapFramebuffer& swap_framebuffer : swap_framebuffers_) { + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyFramebuffer, device, + swap_framebuffer.framebuffer); + } + + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, + swap_pipeline_); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, device, + swap_pipeline_layout_); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyRenderPass, device, + swap_render_pass_); + ui::vulkan::util::DestroyAndNullHandle( dfn.vkDestroyDescriptorPool, device, shared_memory_and_edram_descriptor_pool_); @@ -339,7 +568,7 @@ void VulkanCommandProcessor::ShutdownContext() { deferred_command_buffer_.Reset(); for (const auto& command_buffer_pair : command_buffers_submitted_) { - dfn.vkDestroyCommandPool(device, command_buffer_pair.first.pool, nullptr); + dfn.vkDestroyCommandPool(device, command_buffer_pair.second.pool, nullptr); } command_buffers_submitted_.clear(); for (const CommandBuffer& command_buffer : command_buffers_writable_) { @@ -353,7 +582,7 @@ void VulkanCommandProcessor::ShutdownContext() { frame_open_ = false; for (const auto& semaphore : submissions_in_flight_semaphores_) { - dfn.vkDestroySemaphore(device, semaphore.first, nullptr); + dfn.vkDestroySemaphore(device, semaphore.second, nullptr); } submissions_in_flight_semaphores_.clear(); for (VkFence& fence : submissions_in_flight_fences_) { @@ -377,6 +606,8 @@ void VulkanCommandProcessor::ShutdownContext() { } fences_free_.clear(); + device_lost_ = false; + CommandProcessor::ShutdownContext(); } @@ -432,18 +663,228 @@ void VulkanCommandProcessor::SparseBindBuffer( sparse_bind_wait_stage_mask_ |= wait_stage_mask; } -void VulkanCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, - uint32_t frontbuffer_width, - uint32_t frontbuffer_height) { +void VulkanCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, + uint32_t frontbuffer_width, + uint32_t frontbuffer_height) { // FIXME(Triang3l): frontbuffer_ptr is currently unreliable, in the trace // player it's set to 0, but it's not needed anyway since the fetch constant // contains the address. SCOPE_profile_cpu_f("gpu"); - // In case the swap command is the only one in the frame. - BeginSubmission(true); + ui::Presenter* presenter = graphics_system_->presenter(); + if (!presenter) { + return; + } + // TODO(Triang3l): Resolution scale. + uint32_t resolution_scale = 1; + uint32_t scaled_width = frontbuffer_width * resolution_scale; + uint32_t scaled_height = frontbuffer_height * resolution_scale; + presenter->RefreshGuestOutput( + scaled_width, scaled_height, 1280 * resolution_scale, + 720 * resolution_scale, + [this, scaled_width, scaled_height]( + ui::Presenter::GuestOutputRefreshContext& context) -> bool { + // In case the swap command is the only one in the frame. + if (!BeginSubmission(true)) { + return false; + } + + auto& vulkan_context = static_cast< + ui::vulkan::VulkanPresenter::VulkanGuestOutputRefreshContext&>( + context); + uint64_t guest_output_image_version = vulkan_context.image_version(); + + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + + // Make sure a framebuffer is available for the current guest output + // image version. + size_t swap_framebuffer_index = SIZE_MAX; + size_t swap_framebuffer_new_index = SIZE_MAX; + // Try to find the existing framebuffer for the current guest output + // image version, or an unused (without an existing framebuffer, or with + // one, but that has never actually been used dynamically) slot. + for (size_t i = 0; i < swap_framebuffers_.size(); ++i) { + const SwapFramebuffer& existing_swap_framebuffer = + swap_framebuffers_[i]; + if (existing_swap_framebuffer.framebuffer != VK_NULL_HANDLE && + existing_swap_framebuffer.version == guest_output_image_version) { + swap_framebuffer_index = i; + break; + } + if (existing_swap_framebuffer.framebuffer == VK_NULL_HANDLE || + !existing_swap_framebuffer.last_submission) { + swap_framebuffer_new_index = i; + } + } + if (swap_framebuffer_index == SIZE_MAX) { + if (swap_framebuffer_new_index == SIZE_MAX) { + // Replace the earliest used framebuffer. + swap_framebuffer_new_index = 0; + for (size_t i = 1; i < swap_framebuffers_.size(); ++i) { + if (swap_framebuffers_[i].last_submission < + swap_framebuffers_[swap_framebuffer_new_index] + .last_submission) { + swap_framebuffer_new_index = i; + } + } + } + swap_framebuffer_index = swap_framebuffer_new_index; + SwapFramebuffer& new_swap_framebuffer = + swap_framebuffers_[swap_framebuffer_new_index]; + if (new_swap_framebuffer.framebuffer != VK_NULL_HANDLE) { + if (submission_completed_ >= new_swap_framebuffer.last_submission) { + dfn.vkDestroyFramebuffer(device, new_swap_framebuffer.framebuffer, + nullptr); + } else { + swap_framebuffers_outdated_.emplace_back( + new_swap_framebuffer.last_submission, + new_swap_framebuffer.framebuffer); + } + new_swap_framebuffer.framebuffer = VK_NULL_HANDLE; + } + VkImageView guest_output_image_view_srgb = + vulkan_context.image_view(); + VkFramebufferCreateInfo swap_framebuffer_create_info; + swap_framebuffer_create_info.sType = + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + swap_framebuffer_create_info.pNext = nullptr; + swap_framebuffer_create_info.flags = 0; + swap_framebuffer_create_info.renderPass = swap_render_pass_; + swap_framebuffer_create_info.attachmentCount = 1; + swap_framebuffer_create_info.pAttachments = + &guest_output_image_view_srgb; + swap_framebuffer_create_info.width = scaled_width; + swap_framebuffer_create_info.height = scaled_height; + swap_framebuffer_create_info.layers = 1; + if (dfn.vkCreateFramebuffer( + device, &swap_framebuffer_create_info, nullptr, + &new_swap_framebuffer.framebuffer) != VK_SUCCESS) { + XELOGE("Failed to create the Vulkan framebuffer for presentation"); + return false; + } + new_swap_framebuffer.version = guest_output_image_version; + // The actual submission index will be set if the framebuffer is + // actually used, not dropped due to some error. + new_swap_framebuffer.last_submission = 0; + } + + // End the current render pass before inserting barriers and starting a + // new one. + EndRenderPass(); + + if (vulkan_context.image_ever_written_previously()) { + // Insert a barrier after the last presenter's usage of the guest + // output image. + VkImageMemoryBarrier guest_output_image_acquire_barrier; + guest_output_image_acquire_barrier.sType = + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + guest_output_image_acquire_barrier.pNext = nullptr; + guest_output_image_acquire_barrier.srcAccessMask = + ui::vulkan::VulkanPresenter::kGuestOutputInternalAccessMask; + guest_output_image_acquire_barrier.dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + // Will be overwriting all the contents. + guest_output_image_acquire_barrier.oldLayout = + VK_IMAGE_LAYOUT_UNDEFINED; + // The render pass will do the layout transition, but newLayout must + // not be UNDEFINED. + guest_output_image_acquire_barrier.newLayout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + guest_output_image_acquire_barrier.srcQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + guest_output_image_acquire_barrier.dstQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + guest_output_image_acquire_barrier.image = vulkan_context.image(); + ui::vulkan::util::InitializeSubresourceRange( + guest_output_image_acquire_barrier.subresourceRange); + deferred_command_buffer_.CmdVkPipelineBarrier( + ui::vulkan::VulkanPresenter::kGuestOutputInternalStageMask, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, + nullptr, 1, &guest_output_image_acquire_barrier); + } + + SwapFramebuffer& swap_framebuffer = + swap_framebuffers_[swap_framebuffer_index]; + swap_framebuffer.last_submission = GetCurrentSubmission(); + + VkRenderPassBeginInfo render_pass_begin_info; + render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + render_pass_begin_info.pNext = nullptr; + render_pass_begin_info.renderPass = swap_render_pass_; + render_pass_begin_info.framebuffer = swap_framebuffer.framebuffer; + render_pass_begin_info.renderArea.offset.x = 0; + render_pass_begin_info.renderArea.offset.y = 0; + render_pass_begin_info.renderArea.extent.width = scaled_width; + render_pass_begin_info.renderArea.extent.height = scaled_height; + render_pass_begin_info.clearValueCount = 0; + render_pass_begin_info.pClearValues = nullptr; + deferred_command_buffer_.CmdVkBeginRenderPass( + &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); + + ff_viewport_update_needed_ = true; + ff_scissor_update_needed_ = true; + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = float(scaled_width); + viewport.height = float(scaled_height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + deferred_command_buffer_.CmdVkSetViewport(0, 1, &viewport); + VkRect2D scissor_rect; + scissor_rect.offset.x = 0; + scissor_rect.offset.y = 0; + scissor_rect.extent.width = scaled_width; + scissor_rect.extent.height = scaled_height; + deferred_command_buffer_.CmdVkSetScissor(0, 1, &scissor_rect); + + // Bind a non-emulation graphics pipeline and invalidate the bindings. + current_graphics_pipeline_ = VK_NULL_HANDLE; + current_graphics_pipeline_layout_ = nullptr; + deferred_command_buffer_.CmdVkBindPipeline( + VK_PIPELINE_BIND_POINT_GRAPHICS, swap_pipeline_); + + deferred_command_buffer_.CmdVkDraw(3, 1, 0, 0); + + deferred_command_buffer_.CmdVkEndRenderPass(); + + VkImageMemoryBarrier guest_output_image_release_barrier; + guest_output_image_release_barrier.sType = + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + guest_output_image_release_barrier.pNext = nullptr; + guest_output_image_release_barrier.srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + guest_output_image_release_barrier.dstAccessMask = + ui::vulkan::VulkanPresenter::kGuestOutputInternalAccessMask; + guest_output_image_release_barrier.oldLayout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + guest_output_image_release_barrier.newLayout = + ui::vulkan::VulkanPresenter::kGuestOutputInternalLayout; + guest_output_image_release_barrier.srcQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + guest_output_image_release_barrier.dstQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + guest_output_image_release_barrier.image = vulkan_context.image(); + ui::vulkan::util::InitializeSubresourceRange( + guest_output_image_release_barrier.subresourceRange); + deferred_command_buffer_.CmdVkPipelineBarrier( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + ui::vulkan::VulkanPresenter::kGuestOutputInternalStageMask, 0, 0, + nullptr, 0, nullptr, 1, &guest_output_image_release_barrier); + + // Need to submit all the commands before giving the image back to the + // presenter so it can submit its own commands for displaying it to the + // queue. + EndSubmission(true); + return true; + }); + + // End the frame even if did not present for any reason (the image refresher + // was not called), to prevent leaking per-frame resources. EndSubmission(true); } @@ -454,6 +895,7 @@ void VulkanCommandProcessor::EndRenderPass() { } deferred_command_buffer_.CmdVkEndRenderPass(); current_render_pass_ = VK_NULL_HANDLE; + current_framebuffer_ = VK_NULL_HANDLE; } const VulkanPipelineCache::PipelineLayoutProvider* @@ -469,8 +911,7 @@ VulkanCommandProcessor::GetPipelineLayout(uint32_t texture_count_pixel, } } - const ui::vulkan::VulkanProvider& provider = - GetVulkanContext().GetVulkanProvider(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -675,7 +1116,9 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type, } // TODO(Triang3l): Memory export. - BeginSubmission(true); + if (!BeginSubmission(true)) { + return false; + } // Process primitives. PrimitiveProcessor::ProcessingResult primitive_processing_result; @@ -765,8 +1208,7 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type, current_graphics_pipeline_layout_ = pipeline_layout; } - const ui::vulkan::VulkanProvider& provider = - GetVulkanContext().GetVulkanProvider(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); const VkPhysicalDeviceProperties& device_properties = provider.device_properties(); @@ -925,13 +1367,17 @@ bool VulkanCommandProcessor::IssueCopy() { SCOPE_profile_cpu_f("gpu"); #endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES - BeginSubmission(true); + if (!BeginSubmission(true)) { + return false; + } return true; } void VulkanCommandProcessor::InitializeTrace() { - BeginSubmission(false); + if (!BeginSubmission(true)) { + return; + } bool shared_memory_submitted = shared_memory_->InitializeTraceSubmitDownloads(); if (!shared_memory_submitted) { @@ -943,7 +1389,13 @@ void VulkanCommandProcessor::InitializeTrace() { } } -void VulkanCommandProcessor::CheckSubmissionFence(uint64_t await_submission) { +void VulkanCommandProcessor::CheckSubmissionFenceAndDeviceLoss( + uint64_t await_submission) { + // Only report once, no need to retry a wait that won't succeed anyway. + if (device_lost_) { + return; + } + if (await_submission >= GetCurrentSubmission()) { if (submission_open_) { EndSubmission(false); @@ -953,8 +1405,7 @@ void VulkanCommandProcessor::CheckSubmissionFence(uint64_t await_submission) { await_submission = GetCurrentSubmission() - 1; } - const ui::vulkan::VulkanProvider& provider = - GetVulkanContext().GetVulkanProvider(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -962,26 +1413,40 @@ void VulkanCommandProcessor::CheckSubmissionFence(uint64_t await_submission) { size_t fences_awaited = 0; if (await_submission > submission_completed_) { // Await in a blocking way if requested. - if (dfn.vkWaitForFences(device, - uint32_t(await_submission - submission_completed_), - submissions_in_flight_fences_.data(), VK_TRUE, - UINT64_MAX) == VK_SUCCESS) { + // TODO(Triang3l): Await only one fence. "Fence signal operations that are + // defined by vkQueueSubmit additionally include in the first + // synchronization scope all commands that occur earlier in submission + // order." + VkResult wait_result = dfn.vkWaitForFences( + device, uint32_t(await_submission - submission_completed_), + submissions_in_flight_fences_.data(), VK_TRUE, UINT64_MAX); + if (wait_result == VK_SUCCESS) { fences_awaited += await_submission - submission_completed_; } else { XELOGE("Failed to await submission completion Vulkan fences"); + if (wait_result == VK_ERROR_DEVICE_LOST) { + device_lost_ = true; + } } } // Check how far into the submissions the GPU currently is, in order because // submission themselves can be executed out of order, but Xenia serializes // that for simplicity. while (fences_awaited < fences_total) { - if (dfn.vkWaitForFences(device, 1, - &submissions_in_flight_fences_[fences_awaited], - VK_TRUE, 0) != VK_SUCCESS) { + VkResult fence_status = dfn.vkWaitForFences( + device, 1, &submissions_in_flight_fences_[fences_awaited], VK_TRUE, 0); + if (fence_status != VK_SUCCESS) { + if (fence_status == VK_ERROR_DEVICE_LOST) { + device_lost_ = true; + } break; } ++fences_awaited; } + if (device_lost_) { + graphics_system_->OnHostGpuLossFromAnyThread(true); + return; + } if (!fences_awaited) { // Not updated - no need to reclaim or download things. return; @@ -1002,48 +1467,65 @@ void VulkanCommandProcessor::CheckSubmissionFence(uint64_t await_submission) { while (!submissions_in_flight_semaphores_.empty()) { const auto& semaphore_submission = submissions_in_flight_semaphores_.front(); - if (semaphore_submission.second > submission_completed_) { + if (semaphore_submission.first > submission_completed_) { break; } - semaphores_free_.push_back(semaphore_submission.first); + semaphores_free_.push_back(semaphore_submission.second); submissions_in_flight_semaphores_.pop_front(); } // Reclaim command pools. while (!command_buffers_submitted_.empty()) { const auto& command_buffer_pair = command_buffers_submitted_.front(); - if (command_buffer_pair.second > submission_completed_) { + if (command_buffer_pair.first > submission_completed_) { break; } - command_buffers_writable_.push_back(command_buffer_pair.first); + command_buffers_writable_.push_back(command_buffer_pair.second); command_buffers_submitted_.pop_front(); } shared_memory_->CompletedSubmissionUpdated(); primitive_processor_->CompletedSubmissionUpdated(); + + // Destroy outdated swap objects. + while (!swap_framebuffers_outdated_.empty()) { + const auto& framebuffer_pair = swap_framebuffers_outdated_.front(); + if (framebuffer_pair.first > submission_completed_) { + break; + } + dfn.vkDestroyFramebuffer(device, framebuffer_pair.second, nullptr); + swap_framebuffers_outdated_.pop_front(); + } } -void VulkanCommandProcessor::BeginSubmission(bool is_guest_command) { +bool VulkanCommandProcessor::BeginSubmission(bool is_guest_command) { #if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES SCOPE_profile_cpu_f("gpu"); #endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES + if (device_lost_) { + return false; + } + bool is_opening_frame = is_guest_command && !frame_open_; if (submission_open_ && !is_opening_frame) { - return; + return true; } // Check the fence - needed for all kinds of submissions (to reclaim transient // resources early) and specifically for frames (not to queue too many), and - // await the availability of the current frame. - CheckSubmissionFence( + // await the availability of the current frame. Also check whether the device + // is still available, and whether the await was successful. + uint64_t await_submission = is_opening_frame ? closed_frame_submissions_[frame_current_ % kMaxFramesInFlight] - : 0); - // TODO(Triang3l): If failed to await (completed submission < awaited frame - // submission), do something like dropping the draw command that wanted to - // open the frame. + : 0; + CheckSubmissionFenceAndDeviceLoss(await_submission); + if (device_lost_ || submission_completed_ < await_submission) { + return false; + } + if (is_opening_frame) { // Update the completed frame index, also obtaining the actual completed // frame number (since the CPU may be actually less than 3 frames behind) @@ -1104,10 +1586,12 @@ void VulkanCommandProcessor::BeginSubmission(bool is_guest_command) { primitive_processor_->BeginFrame(); } + + return true; } bool VulkanCommandProcessor::EndSubmission(bool is_swap) { - ui::vulkan::VulkanProvider& provider = GetVulkanContext().GetVulkanProvider(); + ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -1219,8 +1703,14 @@ bool VulkanCommandProcessor::EndSubmission(bool is_swap) { bind_sparse_info.pImageBinds = 0; bind_sparse_info.signalSemaphoreCount = 1; bind_sparse_info.pSignalSemaphores = &bind_sparse_semaphore; - if (provider.BindSparse(1, &bind_sparse_info, VK_NULL_HANDLE) != - VK_SUCCESS) { + VkResult bind_sparse_result; + { + ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition( + provider.AcquireQueue(provider.queue_family_sparse_binding(), 0)); + bind_sparse_result = dfn.vkQueueBindSparse( + queue_acquisition.queue, 1, &bind_sparse_info, VK_NULL_HANDLE); + } + if (bind_sparse_result != VK_SUCCESS) { XELOGE("Failed to submit Vulkan sparse binds"); return false; } @@ -1281,19 +1771,29 @@ bool VulkanCommandProcessor::EndSubmission(bool is_swap) { XELOGE("Failed to reset a Vulkan submission fence"); return false; } - if (provider.SubmitToGraphicsComputeQueue(1, &submit_info, fence) != - VK_SUCCESS) { + VkResult submit_result; + { + ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition( + provider.AcquireQueue(provider.queue_family_graphics_compute(), 0)); + submit_result = + dfn.vkQueueSubmit(queue_acquisition.queue, 1, &submit_info, fence); + } + if (submit_result != VK_SUCCESS) { XELOGE("Failed to submit a Vulkan command buffer"); + if (submit_result == VK_ERROR_DEVICE_LOST && !device_lost_) { + device_lost_ = true; + graphics_system_->OnHostGpuLossFromAnyThread(true); + } return false; } uint64_t submission_current = GetCurrentSubmission(); current_submission_wait_stage_masks_.clear(); for (VkSemaphore semaphore : current_submission_wait_semaphores_) { - submissions_in_flight_semaphores_.emplace_back(semaphore, - submission_current); + submissions_in_flight_semaphores_.emplace_back(submission_current, + semaphore); } current_submission_wait_semaphores_.clear(); - command_buffers_submitted_.emplace_back(command_buffer, submission_current); + command_buffers_submitted_.emplace_back(submission_current, command_buffer); command_buffers_writable_.pop_back(); // Increments the current submission number, going to the next submission. submissions_in_flight_fences_.push_back(fence); @@ -1337,6 +1837,11 @@ bool VulkanCommandProcessor::EndSubmission(bool is_swap) { descriptor_set_layouts_textures_.clear(); primitive_processor_->ClearCache(); + + for (SwapFramebuffer& swap_framebuffer : swap_framebuffers_) { + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyFramebuffer, device, + swap_framebuffer.framebuffer); + } } } @@ -1346,8 +1851,7 @@ bool VulkanCommandProcessor::EndSubmission(bool is_swap) { VkShaderStageFlags VulkanCommandProcessor::GetGuestVertexShaderStageFlags() const { VkShaderStageFlags stages = VK_SHADER_STAGE_VERTEX_BIT; - const ui::vulkan::VulkanProvider& provider = - GetVulkanContext().GetVulkanProvider(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); if (provider.device_features().tessellationShader) { stages |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; } @@ -1685,8 +2189,7 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader, write_fetch_constants.dstSet; } if (write_descriptor_set_count) { - const ui::vulkan::VulkanProvider& provider = - GetVulkanContext().GetVulkanProvider(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); dfn.vkUpdateDescriptorSets(device, write_descriptor_set_count, @@ -1748,8 +2251,7 @@ uint8_t* VulkanCommandProcessor::WriteUniformBufferBinding( if (descriptor_set == VK_NULL_HANDLE) { return nullptr; } - const ui::vulkan::VulkanProvider& provider = - GetVulkanContext().GetVulkanProvider(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); uint8_t* mapping = uniform_buffer_pool_->Request( frame_current_, size, size_t( diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.h b/src/xenia/gpu/vulkan/vulkan_command_processor.h index 0dba7caea..bc43d9ad6 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.h +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.h @@ -10,6 +10,7 @@ #ifndef XENIA_GPU_VULKAN_VULKAN_COMMAND_PROCESSOR_H_ #define XENIA_GPU_VULKAN_VULKAN_COMMAND_PROCESSOR_H_ +#include #include #include #include @@ -31,7 +32,8 @@ #include "xenia/gpu/xenos.h" #include "xenia/kernel/kernel_state.h" #include "xenia/ui/vulkan/transient_descriptor_pool.h" -#include "xenia/ui/vulkan/vulkan_context.h" +#include "xenia/ui/vulkan/vulkan_presenter.h" +#include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h" namespace xe { @@ -48,8 +50,9 @@ class VulkanCommandProcessor : public CommandProcessor { void RestoreEdramSnapshot(const void* snapshot) override; - ui::vulkan::VulkanContext& GetVulkanContext() const { - return static_cast(*context_); + ui::vulkan::VulkanProvider& GetVulkanProvider() const { + return *static_cast( + graphics_system_->provider()); } // Returns the deferred drawing command list for the currently open @@ -93,8 +96,8 @@ class VulkanCommandProcessor : public CommandProcessor { void WriteRegister(uint32_t index, uint32_t value) override; - void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height) override; + void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, + uint32_t frontbuffer_height) override; Shader* LoadShader(xenos::ShaderType shader_type, uint32_t guest_address, const uint32_t* host_address, @@ -159,17 +162,18 @@ class VulkanCommandProcessor : public CommandProcessor { // Rechecks submission number and reclaims per-submission resources. Pass 0 as // the submission to await to simply check status, or pass // GetCurrentSubmission() to wait for all queue operations to be completed. - void CheckSubmissionFence(uint64_t await_submission); + void CheckSubmissionFenceAndDeviceLoss(uint64_t await_submission); // If is_guest_command is true, a new full frame - with full cleanup of // resources and, if needed, starting capturing - is opened if pending (as - // opposed to simply resuming after mid-frame synchronization). - void BeginSubmission(bool is_guest_command); + // opposed to simply resuming after mid-frame synchronization). Returns + // whether a submission is open currently and the device is not lost. + bool BeginSubmission(bool is_guest_command); // If is_swap is true, a full frame is closed - with, if needed, cache // clearing and stopping capturing. Returns whether the submission was done // successfully, if it has failed, leaves it open. bool EndSubmission(bool is_swap); bool AwaitAllQueueOperationsCompletion() { - CheckSubmissionFence(GetCurrentSubmission()); + CheckSubmissionFenceAndDeviceLoss(GetCurrentSubmission()); return !submission_open_ && submissions_in_flight_fences_.empty(); } @@ -188,6 +192,8 @@ class VulkanCommandProcessor : public CommandProcessor { VkDescriptorBufferInfo& descriptor_buffer_info_out, VkWriteDescriptorSet& write_descriptor_set_out); + bool device_lost_ = false; + bool cache_clear_requested_ = false; std::vector fences_free_; @@ -200,7 +206,7 @@ class VulkanCommandProcessor : public CommandProcessor { std::vector current_submission_wait_semaphores_; std::vector current_submission_wait_stage_masks_; std::vector submissions_in_flight_fences_; - std::deque> + std::deque> submissions_in_flight_semaphores_; static constexpr uint32_t kMaxFramesInFlight = 3; @@ -213,7 +219,7 @@ class VulkanCommandProcessor : public CommandProcessor { uint64_t closed_frame_submissions_[kMaxFramesInFlight] = {}; std::vector command_buffers_writable_; - std::deque> command_buffers_submitted_; + std::deque> command_buffers_submitted_; DeferredCommandBuffer deferred_command_buffer_; std::vector sparse_memory_binds_; @@ -260,13 +266,33 @@ class VulkanCommandProcessor : public CommandProcessor { VkDescriptorPool shared_memory_and_edram_descriptor_pool_ = VK_NULL_HANDLE; VkDescriptorSet shared_memory_and_edram_descriptor_set_; + // Has no dependencies on specific pipeline stages on both ends to simplify + // use in different scenarios with different pipelines - use explicit barriers + // for synchronization. Drawing to VK_FORMAT_R8G8B8A8_SRGB. + VkRenderPass swap_render_pass_ = VK_NULL_HANDLE; + VkPipelineLayout swap_pipeline_layout_ = VK_NULL_HANDLE; + VkPipeline swap_pipeline_ = VK_NULL_HANDLE; + + // Framebuffer for the current presenter's guest output image revision, and + // its usage tracking. + struct SwapFramebuffer { + VkFramebuffer framebuffer = VK_NULL_HANDLE; + uint64_t version = UINT64_MAX; + uint64_t last_submission = 0; + }; + std::array + swap_framebuffers_; + std::deque> swap_framebuffers_outdated_; + // The current fixed-function drawing state. VkViewport ff_viewport_; VkRect2D ff_scissor_; bool ff_viewport_update_needed_; bool ff_scissor_update_needed_; - // Cache render pass currently started in the command buffer with framebuffer. + // Cache render pass currently started in the command buffer with the + // framebuffer. VkRenderPass current_render_pass_; VkFramebuffer current_framebuffer_; diff --git a/src/xenia/gpu/vulkan/vulkan_graphics_system.cc b/src/xenia/gpu/vulkan/vulkan_graphics_system.cc index 9f89f1e62..c42510050 100644 --- a/src/xenia/gpu/vulkan/vulkan_graphics_system.cc +++ b/src/xenia/gpu/vulkan/vulkan_graphics_system.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -23,28 +23,16 @@ VulkanGraphicsSystem::~VulkanGraphicsSystem() {} X_STATUS VulkanGraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) { - provider_ = xe::ui::vulkan::VulkanProvider::Create(); - - return GraphicsSystem::Setup(processor, kernel_state, target_window); + ui::WindowedAppContext* app_context, + bool is_surface_required) { + provider_ = xe::ui::vulkan::VulkanProvider::Create(is_surface_required); + return GraphicsSystem::Setup(processor, kernel_state, app_context, + is_surface_required); } -void VulkanGraphicsSystem::Shutdown() { GraphicsSystem::Shutdown(); } - std::unique_ptr VulkanGraphicsSystem::CreateCommandProcessor() { - return std::unique_ptr( - new VulkanCommandProcessor(this, kernel_state_)); -} - -void VulkanGraphicsSystem::Swap(xe::ui::UIEvent* e) { - if (!command_processor_) { - return; - } - - auto& swap_state = command_processor_->swap_state(); - std::lock_guard lock(swap_state.mutex); - swap_state.pending = false; + return std::make_unique(this, kernel_state_); } } // namespace vulkan diff --git a/src/xenia/gpu/vulkan/vulkan_graphics_system.h b/src/xenia/gpu/vulkan/vulkan_graphics_system.h index 76ba8903f..89b97b06c 100644 --- a/src/xenia/gpu/vulkan/vulkan_graphics_system.h +++ b/src/xenia/gpu/vulkan/vulkan_graphics_system.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -29,13 +29,11 @@ class VulkanGraphicsSystem : public GraphicsSystem { std::string name() const override { return "Vulkan Prototype - DO NOT USE"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) override; - void Shutdown() override; + ui::WindowedAppContext* app_context, + bool is_surface_required) override; private: std::unique_ptr CreateCommandProcessor() override; - - void Swap(xe::ui::UIEvent* e) override; }; } // namespace vulkan diff --git a/src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc b/src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc index 30892d079..33d94ad4f 100644 --- a/src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc +++ b/src/xenia/gpu/vulkan/vulkan_pipeline_cache.cc @@ -43,7 +43,7 @@ VulkanPipelineCache::~VulkanPipelineCache() { Shutdown(); } bool VulkanPipelineCache::Initialize() { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); device_pipeline_features_.features = 0; // TODO(Triang3l): Support the portability subset. @@ -64,7 +64,7 @@ void VulkanPipelineCache::Shutdown() { void VulkanPipelineCache::ClearCache() { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -96,9 +96,9 @@ VulkanShader* VulkanPipelineCache::LoadShader(xenos::ShaderType shader_type, // Always create the shader and stash it away. // We need to track it even if it fails translation so we know not to try // again. - VulkanShader* shader = new VulkanShader( - shader_type, data_hash, host_address, dword_count, - command_processor_.GetVulkanContext().GetVulkanProvider()); + VulkanShader* shader = + new VulkanShader(shader_type, data_hash, host_address, dword_count, + command_processor_.GetVulkanProvider()); shaders_.emplace(data_hash, shader); return shader; } @@ -396,15 +396,9 @@ bool VulkanPipelineCache::EnsurePipelineCreated( shader_stage_fragment.pSpecializationInfo = nullptr; } - VkPipelineVertexInputStateCreateInfo vertex_input_state; + VkPipelineVertexInputStateCreateInfo vertex_input_state = {}; vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_state.pNext = nullptr; - vertex_input_state.flags = 0; - vertex_input_state.vertexBindingDescriptionCount = 0; - vertex_input_state.pVertexBindingDescriptions = nullptr; - vertex_input_state.vertexAttributeDescriptionCount = 0; - vertex_input_state.pVertexAttributeDescriptions = nullptr; VkPipelineInputAssemblyStateCreateInfo input_assembly_state; input_assembly_state.sType = @@ -573,10 +567,10 @@ bool VulkanPipelineCache::EnsurePipelineCreated( pipeline_create_info.renderPass = creation_arguments.render_pass; pipeline_create_info.subpass = 0; pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_create_info.basePipelineIndex = 0; + pipeline_create_info.basePipelineIndex = UINT32_MAX; const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); VkPipeline pipeline; diff --git a/src/xenia/gpu/vulkan/vulkan_pipeline_cache.h b/src/xenia/gpu/vulkan/vulkan_pipeline_cache.h index 60654a99d..7ca83a751 100644 --- a/src/xenia/gpu/vulkan/vulkan_pipeline_cache.h +++ b/src/xenia/gpu/vulkan/vulkan_pipeline_cache.h @@ -61,12 +61,10 @@ class VulkanPipelineCache { // Retrieves the shader modification for the current state. The shader must // have microcode analyzed. - SpirvShaderTranslator::Modification - VulkanPipelineCache::GetCurrentVertexShaderModification( + SpirvShaderTranslator::Modification GetCurrentVertexShaderModification( const Shader& shader, Shader::HostVertexShaderType host_vertex_shader_type) const; - SpirvShaderTranslator::Modification - VulkanPipelineCache::GetCurrentPixelShaderModification( + SpirvShaderTranslator::Modification GetCurrentPixelShaderModification( const Shader& shader) const; // TODO(Triang3l): Return a deferred creation handle. diff --git a/src/xenia/gpu/vulkan/vulkan_primitive_processor.cc b/src/xenia/gpu/vulkan/vulkan_primitive_processor.cc index f78a65d7c..5c1dd4168 100644 --- a/src/xenia/gpu/vulkan/vulkan_primitive_processor.cc +++ b/src/xenia/gpu/vulkan/vulkan_primitive_processor.cc @@ -38,7 +38,7 @@ bool VulkanPrimitiveProcessor::Initialize() { } frame_index_buffer_pool_ = std::make_unique( - command_processor_.GetVulkanContext().GetVulkanProvider(), + command_processor_.GetVulkanProvider(), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, std::max(size_t(kMinRequiredConvertedIndexBufferSize), ui::GraphicsUploadBufferPool::kDefaultPageSize)); @@ -47,7 +47,7 @@ bool VulkanPrimitiveProcessor::Initialize() { void VulkanPrimitiveProcessor::Shutdown(bool from_destructor) { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -72,7 +72,7 @@ void VulkanPrimitiveProcessor::CompletedSubmissionUpdated() { command_processor_.GetCompletedSubmission() >= builtin_index_buffer_upload_submission_) { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyBuffer, device, @@ -145,7 +145,7 @@ bool VulkanPrimitiveProcessor::InitializeBuiltin16BitIndexBuffer( assert_true(builtin_index_buffer_upload_memory_ == VK_NULL_HANDLE); const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -199,7 +199,7 @@ bool VulkanPrimitiveProcessor::InitializeBuiltin16BitIndexBuffer( fill_callback(reinterpret_cast(mapping)); ui::vulkan::util::FlushMappedMemoryRange( provider, builtin_index_buffer_memory_, upload_memory_type); - dfn.vkUnmapMemory(device, builtin_index_buffer_memory_); + dfn.vkUnmapMemory(device, builtin_index_buffer_upload_memory_); // Schedule uploading in the first submission. builtin_index_buffer_upload_submission_ = UINT64_MAX; @@ -219,7 +219,7 @@ void* VulkanPrimitiveProcessor::RequestHostConvertedIndexBufferForCurrentFrame( (coalign_for_simd ? XE_GPU_PRIMITIVE_PROCESSOR_SIMD_SIZE : 0), index_size, buffer, offset); if (!mapping) { - return false; + return nullptr; } if (coalign_for_simd) { ptrdiff_t coalignment_offset = diff --git a/src/xenia/gpu/vulkan/vulkan_render_target_cache.cc b/src/xenia/gpu/vulkan/vulkan_render_target_cache.cc index bb9058a82..4a810263b 100644 --- a/src/xenia/gpu/vulkan/vulkan_render_target_cache.cc +++ b/src/xenia/gpu/vulkan/vulkan_render_target_cache.cc @@ -41,7 +41,7 @@ bool VulkanRenderTargetCache::Initialize() { void VulkanRenderTargetCache::Shutdown(bool from_destructor) { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -65,7 +65,7 @@ void VulkanRenderTargetCache::Shutdown(bool from_destructor) { void VulkanRenderTargetCache::ClearCache() { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -385,7 +385,7 @@ VkRenderPass VulkanRenderTargetCache::GetRenderPass(RenderPassKey key) { render_pass_create_info.pDependencies = subpass_dependencies; const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); VkRenderPass render_pass; @@ -491,20 +491,20 @@ VulkanRenderTargetCache::VulkanRenderTarget::~VulkanRenderTarget() { uint32_t VulkanRenderTargetCache::GetMaxRenderTargetWidth() const { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); return provider.device_properties().limits.maxFramebufferWidth; } uint32_t VulkanRenderTargetCache::GetMaxRenderTargetHeight() const { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); return provider.device_properties().limits.maxFramebufferHeight; } RenderTargetCache::RenderTarget* VulkanRenderTargetCache::CreateRenderTarget( RenderTargetKey key) { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -556,47 +556,11 @@ RenderTargetCache::RenderTarget* VulkanRenderTargetCache::CreateRenderTarget( return nullptr; } VkImage image; - if (dfn.vkCreateImage(device, &image_create_info, nullptr, &image) != - VK_SUCCESS) { - // TODO(Triang3l): Error message. - return nullptr; - } - - // Allocate and bind the memory. - - VkMemoryAllocateInfo memory_allocate_info; - VkMemoryRequirements memory_requirements; - dfn.vkGetImageMemoryRequirements(device, image, &memory_requirements); - if (!xe::bit_scan_forward(memory_requirements.memoryTypeBits & - provider.memory_types_device_local(), - &memory_allocate_info.memoryTypeIndex)) { - dfn.vkDestroyImage(device, image, nullptr); - return nullptr; - } - memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info; - if (provider.device_extensions().khr_dedicated_allocation) { - memory_dedicated_allocate_info.sType = - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; - memory_dedicated_allocate_info.pNext = nullptr; - memory_dedicated_allocate_info.image = image; - memory_dedicated_allocate_info.buffer = VK_NULL_HANDLE; - memory_allocate_info.pNext = &memory_dedicated_allocate_info; - } else { - memory_allocate_info.pNext = nullptr; - } - memory_allocate_info.allocationSize = memory_requirements.size; VkDeviceMemory memory; - if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) != - VK_SUCCESS) { + if (!ui::vulkan::util::CreateDedicatedAllocationImage( + provider, image_create_info, + ui::vulkan::util::MemoryPurpose::kDeviceLocal, image, memory)) { // TODO(Triang3l): Error message. - dfn.vkDestroyImage(device, image, nullptr); - return nullptr; - } - if (dfn.vkBindImageMemory(device, image, memory, 0) != VK_SUCCESS) { - // TODO(Triang3l): Error message. - dfn.vkDestroyImage(device, image, nullptr); - dfn.vkFreeMemory(device, memory, nullptr); return nullptr; } @@ -716,7 +680,7 @@ VulkanRenderTargetCache::GetFramebuffer( } const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); diff --git a/src/xenia/gpu/vulkan/vulkan_shared_memory.cc b/src/xenia/gpu/vulkan/vulkan_shared_memory.cc index 1c8fa2e79..9e446c71c 100644 --- a/src/xenia/gpu/vulkan/vulkan_shared_memory.cc +++ b/src/xenia/gpu/vulkan/vulkan_shared_memory.cc @@ -46,7 +46,7 @@ bool VulkanSharedMemory::Initialize() { InitializeCommon(); const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); const VkPhysicalDeviceFeatures& device_features = provider.device_features(); @@ -138,22 +138,26 @@ bool VulkanSharedMemory::Initialize() { return false; } VkMemoryAllocateInfo buffer_memory_allocate_info; + VkMemoryAllocateInfo* buffer_memory_allocate_info_last = + &buffer_memory_allocate_info; buffer_memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + buffer_memory_allocate_info.pNext = nullptr; + buffer_memory_allocate_info.allocationSize = + buffer_memory_requirements.size; + buffer_memory_allocate_info.memoryTypeIndex = buffer_memory_type_; VkMemoryDedicatedAllocateInfoKHR buffer_memory_dedicated_allocate_info; if (provider.device_extensions().khr_dedicated_allocation) { + buffer_memory_allocate_info_last->pNext = + &buffer_memory_dedicated_allocate_info; + buffer_memory_allocate_info_last = + reinterpret_cast( + &buffer_memory_dedicated_allocate_info); buffer_memory_dedicated_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; buffer_memory_dedicated_allocate_info.pNext = nullptr; buffer_memory_dedicated_allocate_info.image = VK_NULL_HANDLE; buffer_memory_dedicated_allocate_info.buffer = buffer_; - buffer_memory_allocate_info.pNext = - &buffer_memory_dedicated_allocate_info; - } else { - buffer_memory_allocate_info.pNext = nullptr; } - buffer_memory_allocate_info.allocationSize = - buffer_memory_requirements.size; - buffer_memory_allocate_info.memoryTypeIndex = buffer_memory_type_; VkDeviceMemory buffer_memory; if (dfn.vkAllocateMemory(device, &buffer_memory_allocate_info, nullptr, &buffer_memory) != VK_SUCCESS) { @@ -190,7 +194,7 @@ void VulkanSharedMemory::Shutdown(bool from_destructor) { last_usage_ = Usage::kTransferDestination; const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -258,7 +262,7 @@ bool VulkanSharedMemory::InitializeTraceSubmitDownloads() { } const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); if (!ui::vulkan::util::CreateDedicatedAllocationBuffer( provider, download_page_count << page_size_log2(), VK_BUFFER_USAGE_TRANSFER_DST_BIT, @@ -313,7 +317,7 @@ void VulkanSharedMemory::InitializeTraceCompleteDownloads() { return; } const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); void* download_mapping; @@ -342,7 +346,7 @@ bool VulkanSharedMemory::AllocateSparseHostGpuMemoryRange( } const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -474,7 +478,7 @@ void VulkanSharedMemory::GetBarrier(Usage usage, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); if (provider.device_features().tessellationShader) { stage_mask |= VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT; } @@ -495,7 +499,7 @@ void VulkanSharedMemory::GetBarrier(Usage usage, void VulkanSharedMemory::ResetTraceDownload() { const ui::vulkan::VulkanProvider& provider = - command_processor_.GetVulkanContext().GetVulkanProvider(); + command_processor_.GetVulkanProvider(); const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyBuffer, device, diff --git a/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc b/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc new file mode 100644 index 000000000..4483129b8 --- /dev/null +++ b/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc @@ -0,0 +1,63 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/console_app_main.h" +#include "xenia/base/logging.h" +#include "xenia/gpu/trace_dump.h" +#include "xenia/gpu/vulkan/vulkan_command_processor.h" +#include "xenia/gpu/vulkan/vulkan_graphics_system.h" +#include "xenia/ui/vulkan/vulkan_provider.h" + +namespace xe { +namespace gpu { +namespace vulkan { + +using namespace xe::gpu::xenos; + +class VulkanTraceDump : public TraceDump { + public: + std::unique_ptr CreateGraphicsSystem() override { + return std::unique_ptr(new VulkanGraphicsSystem()); + } + + void BeginHostCapture() override { + const RENDERDOC_API_1_0_0* renderdoc_api = + static_cast( + graphics_system_->provider()) + ->renderdoc_api() + .api_1_0_0(); + if (renderdoc_api && !renderdoc_api->IsFrameCapturing()) { + renderdoc_api->StartFrameCapture(nullptr, nullptr); + } + } + + void EndHostCapture() override { + const RENDERDOC_API_1_0_0* renderdoc_api = + static_cast( + graphics_system_->provider()) + ->renderdoc_api() + .api_1_0_0(); + if (renderdoc_api && renderdoc_api->IsFrameCapturing()) { + renderdoc_api->EndFrameCapture(nullptr, nullptr); + } + } +}; + +int trace_dump_main(const std::vector& args) { + VulkanTraceDump trace_dump; + return trace_dump.Main(args); +} + +} // namespace vulkan +} // namespace gpu +} // namespace xe + +XE_DEFINE_CONSOLE_APP("xenia-gpu-vulkan-trace-dump", + xe::gpu::vulkan::trace_dump_main, "some.trace", + "target_trace_file"); diff --git a/src/xenia/hid/hid_demo.cc b/src/xenia/hid/hid_demo.cc index 6dff015da..f4d616f9e 100644 --- a/src/xenia/hid/hid_demo.cc +++ b/src/xenia/hid/hid_demo.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -24,10 +24,14 @@ #include "xenia/base/threading.h" #include "xenia/hid/hid_flags.h" #include "xenia/hid/input_system.h" +#include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" // Available input drivers: @@ -59,12 +63,41 @@ class HidDemoApp final : public ui::WindowedApp { bool OnInitialize() override; private: + enum : size_t { + kZOrderHidInput, + kZOrderImGui, + }; + + class HidDemoWindowListener final : public ui::WindowListener { + public: + explicit HidDemoWindowListener(ui::WindowedAppContext& app_context) + : app_context_(app_context) {} + void OnClosing(ui::UIEvent& e) override { app_context_.QuitFromUIThread(); } + + private: + ui::WindowedAppContext& app_context_; + }; + + class HidDemoDialog final : public ui::ImGuiDialog { + public: + explicit HidDemoDialog(ui::ImGuiDrawer* imgui_drawer, HidDemoApp& app) + : ui::ImGuiDialog(imgui_drawer), app_(app) {} + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + HidDemoApp& app_; + }; + explicit HidDemoApp(ui::WindowedAppContext& app_context) - : ui::WindowedApp(app_context, "xenia-hid-demo") {} + : ui::WindowedApp(app_context, "xenia-hid-demo"), + window_listener_(app_context) {} static std::vector> CreateInputDrivers( ui::Window* window); + void Draw(ImGuiIO& io); void DrawUserInputGetState(uint32_t user_index) const; void DrawInputGetState() const; void DrawUserInputGetKeystroke(uint32_t user_index, bool poll, @@ -72,9 +105,15 @@ class HidDemoApp final : public ui::WindowedApp { void DrawInputGetKeystroke(bool poll, bool hide_repeats, bool clear_log) const; + HidDemoWindowListener window_listener_; std::unique_ptr graphics_provider_; std::unique_ptr window_; std::unique_ptr input_system_; + std::unique_ptr presenter_; + std::unique_ptr immediate_drawer_; + std::unique_ptr imgui_drawer_; + std::unique_ptr demo_dialog_; + bool is_active_ = true; }; @@ -82,71 +121,64 @@ std::vector> HidDemoApp::CreateInputDrivers( ui::Window* window) { std::vector> drivers; if (cvars::hid.compare("nop") == 0) { - drivers.emplace_back(xe::hid::nop::Create(window)); + drivers.emplace_back(xe::hid::nop::Create(window, kZOrderHidInput)); } else if (cvars::hid.compare("sdl") == 0) { - auto driver = xe::hid::sdl::Create(window); + auto driver = xe::hid::sdl::Create(window, kZOrderHidInput); if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } #if XE_PLATFORM_WIN32 } else if (cvars::hid.compare("winkey") == 0) { - auto driver = xe::hid::winkey::Create(window); + auto driver = xe::hid::winkey::Create(window, kZOrderHidInput); if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } } else if (cvars::hid.compare("xinput") == 0) { - auto driver = xe::hid::xinput::Create(window); + auto driver = xe::hid::xinput::Create(window, kZOrderHidInput); if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } #endif // XE_PLATFORM_WIN32 } else { - auto sdl_driver = xe::hid::sdl::Create(window); + auto sdl_driver = xe::hid::sdl::Create(window, kZOrderHidInput); if (sdl_driver && XSUCCEEDED(sdl_driver->Setup())) { drivers.emplace_back(std::move(sdl_driver)); } #if XE_PLATFORM_WIN32 - auto xinput_driver = xe::hid::xinput::Create(window); + auto xinput_driver = xe::hid::xinput::Create(window, kZOrderHidInput); if (xinput_driver && XSUCCEEDED(xinput_driver->Setup())) { drivers.emplace_back(std::move(xinput_driver)); } - auto winkey_driver = xe::hid::winkey::Create(window); + auto winkey_driver = xe::hid::winkey::Create(window, kZOrderHidInput); if (winkey_driver && XSUCCEEDED(winkey_driver->Setup())) { drivers.emplace_back(std::move(winkey_driver)); } #endif // XE_PLATFORM_WIN32 if (drivers.empty()) { // Fallback to nop if none created. - drivers.emplace_back(xe::hid::nop::Create(window)); + drivers.emplace_back(xe::hid::nop::Create(window, kZOrderHidInput)); } } return drivers; } bool HidDemoApp::OnInitialize() { - // Create graphics provider that provides the context for the window. - graphics_provider_ = xe::ui::vulkan::VulkanProvider::Create(); + // Create the graphics provider that provides the presenter for the window. + graphics_provider_ = xe::ui::vulkan::VulkanProvider::Create(true); if (!graphics_provider_) { + XELOGE("Failed to initialize the graphics provider"); return false; } - // Create the window. - window_ = xe::ui::Window::Create(app_context(), GetName()); - if (!window_->Initialize()) { - XELOGE("Failed to initialize main window"); + // Create and configure the window. + window_ = xe::ui::Window::Create(app_context(), GetName(), + COL_WIDTH_STATE + COL_WIDTH_STROKE, + ROW_HEIGHT_GENERAL + 500); + window_->AddListener(&window_listener_); + if (!window_->Open()) { + XELOGE("Failed to open the main window"); return false; } - window_->on_closed.AddListener([this](xe::ui::UIEvent* e) { - XELOGI("User-initiated death!"); - app_context().QuitFromUIThread(); - }); - - // Initial size setting, done here so that it knows the menu exists. - window_->Resize(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL + 500); - - // Create the graphics context for the window. The window will finish - // initialization with the context (loading resources, etc). - window_->set_context(graphics_provider_->CreateHostContext(window_.get())); // Initialize input system and all drivers. input_system_ = std::make_unique(window_.get()); @@ -157,71 +189,83 @@ bool HidDemoApp::OnInitialize() { input_system_->AddDriver(std::move(driver)); } - window_->Invalidate(); - - window_->set_imgui_input_enabled(true); - - window_->on_painting.AddListener([this](xe::ui::UIEvent* e) { - auto& io = window_->imgui_drawer()->GetIO(); - - const ImGuiWindowFlags wflags = - ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_NoScrollbar; - - ImGui::Begin("General", nullptr, wflags); - { - ImGui::SetWindowPos(ImVec2(0, 0)); - ImGui::SetWindowSize( - ImVec2(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL)); - - ImGui::Text("Input System (hid) = \"%s\"", cvars::hid.c_str()); - ImGui::Checkbox("is_active", &is_active_); - } - ImGui::End(); - - ImGui::Begin("GetState()", nullptr, wflags); - { - ImGui::SetWindowPos(ImVec2(0, ROW_HEIGHT_GENERAL)); - ImGui::SetWindowSize( - ImVec2(COL_WIDTH_STATE, io.DisplaySize.y - ROW_HEIGHT_GENERAL)); - - static bool enable_GetState = false; - ImGui::Checkbox("Active", &enable_GetState); - ImGui::SameLine(); - ImGui::Checkbox("Guide Button", &cvars::guide_button); - if (enable_GetState) { - ImGui::Spacing(); - DrawInputGetState(); - } - } - ImGui::End(); - - ImGui::Begin("GetKeystroke()", nullptr, wflags); - { - ImGui::SetWindowPos(ImVec2(COL_WIDTH_STATE, ROW_HEIGHT_GENERAL)); - ImGui::SetWindowSize( - ImVec2(COL_WIDTH_STROKE, io.DisplaySize.y - ROW_HEIGHT_GENERAL)); - - static bool enable_GetKeystroke = false; - static bool hide_repeats = false; - ImGui::Checkbox("Active", &enable_GetKeystroke); - ImGui::SameLine(); - ImGui::Checkbox("Hide repeats", &hide_repeats); - ImGui::SameLine(); - const bool clear_log = ImGui::Button("Clear"); - ImGui::Spacing(); - DrawInputGetKeystroke(enable_GetKeystroke, hide_repeats, clear_log); - } - ImGui::End(); - - // Continuous paint. - window_->Invalidate(); - }); + // Setup drawing to the window. + presenter_ = graphics_provider_->CreatePresenter(); + if (!presenter_) { + XELOGE("Failed to initialize the presenter"); + return false; + } + immediate_drawer_ = graphics_provider_->CreateImmediateDrawer(); + if (!immediate_drawer_) { + XELOGE("Failed to initialize the immediate drawer"); + return false; + } + immediate_drawer_->SetPresenter(presenter_.get()); + imgui_drawer_ = + std::make_unique(window_.get(), kZOrderImGui); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + immediate_drawer_.get()); + demo_dialog_ = std::make_unique(imgui_drawer_.get(), *this); + window_->SetPresenter(presenter_.get()); return true; } +void HidDemoApp::HidDemoDialog::OnDraw(ImGuiIO& io) { app_.Draw(io); } + +void HidDemoApp::Draw(ImGuiIO& io) { + const ImGuiWindowFlags wflags = + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoScrollbar; + + ImGui::Begin("General", nullptr, wflags); + { + ImGui::SetWindowPos(ImVec2(0, 0)); + ImGui::SetWindowSize( + ImVec2(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL)); + + ImGui::Text("Input System (hid) = \"%s\"", cvars::hid.c_str()); + ImGui::Checkbox("is_active", &is_active_); + } + ImGui::End(); + + ImGui::Begin("GetState()", nullptr, wflags); + { + ImGui::SetWindowPos(ImVec2(0, ROW_HEIGHT_GENERAL)); + ImGui::SetWindowSize( + ImVec2(COL_WIDTH_STATE, io.DisplaySize.y - ROW_HEIGHT_GENERAL)); + + static bool enable_GetState = false; + ImGui::Checkbox("Active", &enable_GetState); + ImGui::SameLine(); + ImGui::Checkbox("Guide Button", &cvars::guide_button); + if (enable_GetState) { + ImGui::Spacing(); + DrawInputGetState(); + } + } + ImGui::End(); + + ImGui::Begin("GetKeystroke()", nullptr, wflags); + { + ImGui::SetWindowPos(ImVec2(COL_WIDTH_STATE, ROW_HEIGHT_GENERAL)); + ImGui::SetWindowSize( + ImVec2(COL_WIDTH_STROKE, io.DisplaySize.y - ROW_HEIGHT_GENERAL)); + + static bool enable_GetKeystroke = false; + static bool hide_repeats = false; + ImGui::Checkbox("Active", &enable_GetKeystroke); + ImGui::SameLine(); + ImGui::Checkbox("Hide repeats", &hide_repeats); + ImGui::SameLine(); + const bool clear_log = ImGui::Button("Clear"); + ImGui::Spacing(); + DrawInputGetKeystroke(enable_GetKeystroke, hide_repeats, clear_log); + } + ImGui::End(); +} + void HidDemoApp::DrawUserInputGetState(uint32_t user_index) const { ImGui::Text("User %u:", user_index); diff --git a/src/xenia/hid/input_driver.h b/src/xenia/hid/input_driver.h index aef8cffeb..6b0ff3472 100644 --- a/src/xenia/hid/input_driver.h +++ b/src/xenia/hid/input_driver.h @@ -10,6 +10,7 @@ #ifndef XENIA_HID_INPUT_DRIVER_H_ #define XENIA_HID_INPUT_DRIVER_H_ +#include #include #include "xenia/hid/input.h" @@ -29,7 +30,7 @@ class InputSystem; class InputDriver { public: - virtual ~InputDriver(); + virtual ~InputDriver() = default; virtual X_STATUS Setup() = 0; @@ -45,18 +46,21 @@ class InputDriver { is_active_callback_ = is_active_callback; } - private: - xe::ui::Window* window_ = nullptr; - std::function is_active_callback_ = nullptr; - protected: - explicit InputDriver(xe::ui::Window* window); + explicit InputDriver(xe::ui::Window* window, size_t window_z_order) + : window_(window), window_z_order_(window_z_order) {} xe::ui::Window* window() const { return window_; } + size_t window_z_order() const { return window_z_order_; } bool is_active() const { return !is_active_callback_ || is_active_callback_(); } + + private: + xe::ui::Window* window_; + size_t window_z_order_; + std::function is_active_callback_ = nullptr; }; } // namespace hid diff --git a/src/xenia/hid/nop/nop_hid.cc b/src/xenia/hid/nop/nop_hid.cc index 54765df5f..4d198b278 100644 --- a/src/xenia/hid/nop/nop_hid.cc +++ b/src/xenia/hid/nop/nop_hid.cc @@ -15,8 +15,9 @@ namespace xe { namespace hid { namespace nop { -std::unique_ptr Create(xe::ui::Window* window) { - return std::make_unique(window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order) { + return std::make_unique(window, window_z_order); } } // namespace nop diff --git a/src/xenia/hid/nop/nop_hid.h b/src/xenia/hid/nop/nop_hid.h index c2ea0a037..6d8f36016 100644 --- a/src/xenia/hid/nop/nop_hid.h +++ b/src/xenia/hid/nop/nop_hid.h @@ -18,7 +18,8 @@ namespace xe { namespace hid { namespace nop { -std::unique_ptr Create(xe::ui::Window* window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order); } // namespace nop } // namespace hid diff --git a/src/xenia/hid/nop/nop_input_driver.cc b/src/xenia/hid/nop/nop_input_driver.cc index bd22d65e2..da6897459 100644 --- a/src/xenia/hid/nop/nop_input_driver.cc +++ b/src/xenia/hid/nop/nop_input_driver.cc @@ -15,7 +15,8 @@ namespace xe { namespace hid { namespace nop { -NopInputDriver::NopInputDriver(xe::ui::Window* window) : InputDriver(window) {} +NopInputDriver::NopInputDriver(xe::ui::Window* window, size_t window_z_order) + : InputDriver(window, window_z_order) {} NopInputDriver::~NopInputDriver() = default; diff --git a/src/xenia/hid/nop/nop_input_driver.h b/src/xenia/hid/nop/nop_input_driver.h index be949f016..361b63a7f 100644 --- a/src/xenia/hid/nop/nop_input_driver.h +++ b/src/xenia/hid/nop/nop_input_driver.h @@ -16,9 +16,9 @@ namespace xe { namespace hid { namespace nop { -class NopInputDriver : public InputDriver { +class NopInputDriver final : public InputDriver { public: - explicit NopInputDriver(xe::ui::Window* window); + explicit NopInputDriver(xe::ui::Window* window, size_t window_z_order); ~NopInputDriver() override; X_STATUS Setup() override; diff --git a/src/xenia/hid/premake5.lua b/src/xenia/hid/premake5.lua index 1aeef5657..eaaa792e4 100644 --- a/src/xenia/hid/premake5.lua +++ b/src/xenia/hid/premake5.lua @@ -41,7 +41,6 @@ project("xenia-hid-demo") filter("platforms:Linux") links({ "SDL2", - "vulkan", "X11", "xcb", "X11-xcb", diff --git a/src/xenia/hid/sdl/sdl_hid.cc b/src/xenia/hid/sdl/sdl_hid.cc index 336423ae2..cc20274b9 100644 --- a/src/xenia/hid/sdl/sdl_hid.cc +++ b/src/xenia/hid/sdl/sdl_hid.cc @@ -15,8 +15,9 @@ namespace xe { namespace hid { namespace sdl { -std::unique_ptr Create(xe::ui::Window* window) { - return std::make_unique(window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order) { + return std::make_unique(window, window_z_order); } } // namespace sdl diff --git a/src/xenia/hid/sdl/sdl_hid.h b/src/xenia/hid/sdl/sdl_hid.h index ba02f0d6c..7bedd8c03 100644 --- a/src/xenia/hid/sdl/sdl_hid.h +++ b/src/xenia/hid/sdl/sdl_hid.h @@ -18,7 +18,8 @@ namespace xe { namespace hid { namespace sdl { -std::unique_ptr Create(xe::ui::Window* window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order); } // namespace sdl } // namespace hid diff --git a/src/xenia/hid/sdl/sdl_input_driver.cc b/src/xenia/hid/sdl/sdl_input_driver.cc index 6b348f285..044c7dcd0 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.cc +++ b/src/xenia/hid/sdl/sdl_input_driver.cc @@ -33,8 +33,8 @@ namespace xe { namespace hid { namespace sdl { -SDLInputDriver::SDLInputDriver(xe::ui::Window* window) - : InputDriver(window), +SDLInputDriver::SDLInputDriver(xe::ui::Window* window, size_t window_z_order) + : InputDriver(window, window_z_order), sdl_events_initialized_(false), sdl_gamecontroller_initialized_(false), sdl_events_unflushed_(0), diff --git a/src/xenia/hid/sdl/sdl_input_driver.h b/src/xenia/hid/sdl/sdl_input_driver.h index 367206cdb..de5c48e7c 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.h +++ b/src/xenia/hid/sdl/sdl_input_driver.h @@ -28,9 +28,9 @@ namespace xe { namespace hid { namespace sdl { -class SDLInputDriver : public InputDriver { +class SDLInputDriver final : public InputDriver { public: - explicit SDLInputDriver(xe::ui::Window* window); + explicit SDLInputDriver(xe::ui::Window* window, size_t window_z_order); ~SDLInputDriver() override; X_STATUS Setup() override; @@ -42,7 +42,7 @@ class SDLInputDriver : public InputDriver { X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags, X_INPUT_KEYSTROKE* out_keystroke) override; - protected: + private: struct ControllerState { SDL_GameController* sdl; X_INPUT_CAPABILITIES caps; @@ -65,7 +65,6 @@ class SDLInputDriver : public InputDriver { uint32_t repeat_time; }; - protected: void HandleEvent(const SDL_Event& event); void OnControllerDeviceAdded(const SDL_Event& event); void OnControllerDeviceRemoved(const SDL_Event& event); @@ -80,7 +79,6 @@ class SDLInputDriver : public InputDriver { void UpdateXCapabilities(ControllerState& state); void QueueControllerUpdate(); - protected: bool sdl_events_initialized_; bool sdl_gamecontroller_initialized_; int sdl_events_unflushed_; diff --git a/src/xenia/hid/winkey/winkey_binding_table.inc b/src/xenia/hid/winkey/winkey_binding_table.inc new file mode 100644 index 000000000..c11b277a0 --- /dev/null +++ b/src/xenia/hid/winkey/winkey_binding_table.inc @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +// This is a partial file designed to be included by other files when +// constructing various tables. + +// clang-format off +XE_HID_WINKEY_BINDING(DpadLeft, "DPAD_LEFT" , keybind_dpad_left , "^A" ) +XE_HID_WINKEY_BINDING(DpadRight, "DPAD_RIGHT" , keybind_dpad_right , "^D" ) +XE_HID_WINKEY_BINDING(DpadDown, "DPAD_DOWN" , keybind_dpad_down , "^S" ) +XE_HID_WINKEY_BINDING(DpadUp, "DPAD_UP" , keybind_dpad_up , "^W" ) +XE_HID_WINKEY_BINDING(LThumbLeft, "LEFT_THUMB_LEFT" , keybind_left_thumb_left , "_A" ) +XE_HID_WINKEY_BINDING(LThumbRight, "LEFT_THUMB_RIGHT" , keybind_left_thumb_right , "_D" ) +XE_HID_WINKEY_BINDING(LThumbDown, "LEFT_THUMB_DOWN" , keybind_left_thumb_down , "_S" ) +XE_HID_WINKEY_BINDING(LThumbUp, "LEFT_THUMB_UP" , keybind_left_thumb_up , "_W" ) +XE_HID_WINKEY_BINDING(LThumbPress, "LEFT_THUMB_PRESSED" , keybind_left_thumb , "F" ) +XE_HID_WINKEY_BINDING(RThumbUp, "RIGHT_THUMB_UP" , keybind_right_thumb_up , "0x26") +XE_HID_WINKEY_BINDING(RThumbDown, "RIGHT_THUMB_DOWN" , keybind_right_thumb_down , "0x28") +XE_HID_WINKEY_BINDING(RThumbRight, "RIGHT_THUMB_RIGHT" , keybind_right_thumb_right, "0x27") +XE_HID_WINKEY_BINDING(RThumbLeft, "RIGHT_THUMB_LEFT" , keybind_right_thumb_left , "0x25") +XE_HID_WINKEY_BINDING(RThumbPress, "RIGHT_THUMB_PRESSED", keybind_right_thumb , "K" ) +XE_HID_WINKEY_BINDING(X, "X" , keybind_x , "L" ) +XE_HID_WINKEY_BINDING(B, "B" , keybind_b , "0xDE") +XE_HID_WINKEY_BINDING(A, "A" , keybind_a , "0xBA") +XE_HID_WINKEY_BINDING(Y, "Y" , keybind_y , "P" ) +XE_HID_WINKEY_BINDING(LTrigger, "LEFT_TRIGGER" , keybind_left_trigger , "Q I" ) +XE_HID_WINKEY_BINDING(RTrigger, "RIGHT_TRIGGER" , keybind_right_trigger , "E O" ) +XE_HID_WINKEY_BINDING(Back, "BACK" , keybind_back , "Z" ) +XE_HID_WINKEY_BINDING(Start, "START" , keybind_start , "X" ) +XE_HID_WINKEY_BINDING(LShoulder, "LEFT_SHOULDER" , keybind_left_shoulder , "1" ) +XE_HID_WINKEY_BINDING(RShoulder, "RIGHT_SHOULDER" , keybind_right_shoulder , "3" ) +// clang-format on diff --git a/src/xenia/hid/winkey/winkey_hid.cc b/src/xenia/hid/winkey/winkey_hid.cc index 7244f4c53..2f75ef5c4 100644 --- a/src/xenia/hid/winkey/winkey_hid.cc +++ b/src/xenia/hid/winkey/winkey_hid.cc @@ -15,8 +15,9 @@ namespace xe { namespace hid { namespace winkey { -std::unique_ptr Create(xe::ui::Window* window) { - return std::make_unique(window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order) { + return std::make_unique(window, window_z_order); } } // namespace winkey diff --git a/src/xenia/hid/winkey/winkey_hid.h b/src/xenia/hid/winkey/winkey_hid.h index a17e5ba98..6061c6a06 100644 --- a/src/xenia/hid/winkey/winkey_hid.h +++ b/src/xenia/hid/winkey/winkey_hid.h @@ -18,7 +18,8 @@ namespace xe { namespace hid { namespace winkey { -std::unique_ptr Create(xe::ui::Window* window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order); } // namespace winkey } // namespace hid diff --git a/src/xenia/hid/winkey/winkey_input_driver.cc b/src/xenia/hid/winkey/winkey_input_driver.cc index ba0b12cdf..53c5ef359 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.cc +++ b/src/xenia/hid/winkey/winkey_input_driver.cc @@ -2,57 +2,100 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/hid/winkey/winkey_input_driver.h" +#include "xenia/base/logging.h" #include "xenia/base/platform_win.h" #include "xenia/hid/hid_flags.h" #include "xenia/hid/input_system.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" +#define XE_HID_WINKEY_BINDING(button, description, cvar_name, \ + cvar_default_value) \ + DEFINE_string(cvar_name, cvar_default_value, \ + "List of keys to bind to " description \ + ", separated by spaces", \ + "HID.WinKey") +#include "winkey_binding_table.inc" +#undef XE_HID_WINKEY_BINDING + namespace xe { namespace hid { namespace winkey { -WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window) - : InputDriver(window), packet_number_(1) { - // Register a key listener. - window->on_key_down.AddListener([this](ui::KeyEvent* evt) { - if (!is_active()) { - return; - } - - auto global_lock = global_critical_region_.Acquire(); - - KeyEvent key; - key.virtual_key = evt->virtual_key(); - key.transition = true; - key.prev_state = evt->prev_state(); - key.repeat_count = evt->repeat_count(); - key_events_.push(key); - }); - window->on_key_up.AddListener([this](ui::KeyEvent* evt) { - if (!is_active()) { - return; - } - - auto global_lock = global_critical_region_.Acquire(); - - KeyEvent key; - key.virtual_key = evt->virtual_key(); - key.transition = false; - key.prev_state = evt->prev_state(); - key.repeat_count = evt->repeat_count(); - key_events_.push(key); - }); +bool __inline IsKeyToggled(uint8_t key) { + return (GetKeyState(key) & 0x1) == 0x1; } -WinKeyInputDriver::~WinKeyInputDriver() = default; +bool __inline IsKeyDown(uint8_t key) { + return (GetAsyncKeyState(key) & 0x8000) == 0x8000; +} + +bool __inline IsKeyDown(ui::VirtualKey virtual_key) { + return IsKeyDown(static_cast(virtual_key)); +} + +void WinKeyInputDriver::ParseKeyBinding(ui::VirtualKey output_key, + const std::string_view description, + const std::string_view source_tokens) { + for (const std::string_view source_token : + utf8::split(source_tokens, " ", true)) { + KeyBinding key_binding; + key_binding.output_key = output_key; + + std::string_view token = source_token; + + if (utf8::starts_with(token, "_")) { + key_binding.lowercase = true; + token = token.substr(1); + } else if (utf8::starts_with(token, "^")) { + key_binding.uppercase = true; + token = token.substr(1); + } + + if (utf8::starts_with(token, "0x")) { + token = token.substr(2); + key_binding.input_key = static_cast( + string_util::from_string(token, true)); + } else if (token.size() == 1 && (token[0] >= 'A' && token[0] <= 'Z') || + (token[0] >= '0' && token[0] <= '9')) { + key_binding.input_key = static_cast(token[0]); + } + + if (key_binding.input_key == ui::VirtualKey::kNone) { + XELOGW("winkey: failed to parse binding \"{}\" for controller input {}.", + source_token, description); + continue; + } + + key_bindings_.push_back(key_binding); + XELOGI("winkey: \"{}\" binds key 0x{:X} to controller input {}.", + source_token, key_binding.input_key, description); + } +} + +WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window, + size_t window_z_order) + : InputDriver(window, window_z_order), window_input_listener_(*this) { +#define XE_HID_WINKEY_BINDING(button, description, cvar_name, \ + cvar_default_value) \ + ParseKeyBinding(xe::ui::VirtualKey::kXInputPad##button, description, \ + cvars::cvar_name); +#include "winkey_binding_table.inc" +#undef XE_HID_WINKEY_BINDING + + window->AddInputListener(&window_input_listener_, window_z_order); +} + +WinKeyInputDriver::~WinKeyInputDriver() { + window()->RemoveInputListener(&window_input_listener_); +} X_STATUS WinKeyInputDriver::Setup() { return X_STATUS_SUCCESS; } @@ -78,9 +121,6 @@ X_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags, return X_ERROR_SUCCESS; } -#define IS_KEY_TOGGLED(key) ((GetKeyState(key) & 0x1) == 0x1) -#define IS_KEY_DOWN(key) ((GetAsyncKeyState(key) & 0x8000) == 0x8000) - X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, X_INPUT_STATE* out_state) { if (user_index != 0) { @@ -97,115 +137,87 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, int16_t thumb_rx = 0; int16_t thumb_ry = 0; - if (window()->has_focus() && is_active()) { - if (IS_KEY_TOGGLED(VK_CAPITAL) || IS_KEY_DOWN(VK_SHIFT)) { - // dpad toggled - if (IS_KEY_DOWN('A')) { - // A - buttons |= 0x0004; // XINPUT_GAMEPAD_DPAD_LEFT + if (window()->HasFocus() && is_active()) { + bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT); + for (const KeyBinding& b : key_bindings_) { + if (((b.lowercase == b.uppercase) || (b.lowercase && !capital) || + (b.uppercase && capital)) && + IsKeyDown(b.input_key)) { + switch (b.output_key) { + case ui::VirtualKey::kXInputPadA: + buttons |= 0x1000; // XINPUT_GAMEPAD_A + break; + case ui::VirtualKey::kXInputPadY: + buttons |= 0x8000; // XINPUT_GAMEPAD_Y + break; + case ui::VirtualKey::kXInputPadB: + buttons |= 0x2000; // XINPUT_GAMEPAD_B + break; + case ui::VirtualKey::kXInputPadX: + buttons |= 0x4000; // XINPUT_GAMEPAD_X + break; + case ui::VirtualKey::kXInputPadDpadLeft: + buttons |= 0x0004; // XINPUT_GAMEPAD_DPAD_LEFT + break; + case ui::VirtualKey::kXInputPadDpadRight: + buttons |= 0x0008; // XINPUT_GAMEPAD_DPAD_RIGHT + break; + case ui::VirtualKey::kXInputPadDpadDown: + buttons |= 0x0002; // XINPUT_GAMEPAD_DPAD_DOWN + break; + case ui::VirtualKey::kXInputPadDpadUp: + buttons |= 0x0001; // XINPUT_GAMEPAD_DPAD_UP + break; + case ui::VirtualKey::kXInputPadRThumbPress: + buttons |= 0x0080; // XINPUT_GAMEPAD_RIGHT_THUMB + break; + case ui::VirtualKey::kXInputPadLThumbPress: + buttons |= 0x0040; // XINPUT_GAMEPAD_LEFT_THUMB + break; + case ui::VirtualKey::kXInputPadBack: + buttons |= 0x0020; // XINPUT_GAMEPAD_BACK + break; + case ui::VirtualKey::kXInputPadStart: + buttons |= 0x0010; // XINPUT_GAMEPAD_START + break; + case ui::VirtualKey::kXInputPadLShoulder: + buttons |= 0x0100; // XINPUT_GAMEPAD_LEFT_SHOULDER + break; + case ui::VirtualKey::kXInputPadRShoulder: + buttons |= 0x0200; // XINPUT_GAMEPAD_RIGHT_SHOULDER + break; + case ui::VirtualKey::kXInputPadLTrigger: + left_trigger = 0xFF; + break; + case ui::VirtualKey::kXInputPadRTrigger: + right_trigger = 0xFF; + break; + case ui::VirtualKey::kXInputPadLThumbLeft: + thumb_lx += SHRT_MIN; + break; + case ui::VirtualKey::kXInputPadLThumbRight: + thumb_lx += SHRT_MAX; + break; + case ui::VirtualKey::kXInputPadLThumbDown: + thumb_ly += SHRT_MIN; + break; + case ui::VirtualKey::kXInputPadLThumbUp: + thumb_ly += SHRT_MAX; + break; + case ui::VirtualKey::kXInputPadRThumbUp: + thumb_ry += SHRT_MAX; + break; + case ui::VirtualKey::kXInputPadRThumbDown: + thumb_ry += SHRT_MIN; + break; + case ui::VirtualKey::kXInputPadRThumbRight: + thumb_rx += SHRT_MAX; + break; + case ui::VirtualKey::kXInputPadRThumbLeft: + thumb_rx += SHRT_MIN; + break; + } } - if (IS_KEY_DOWN('D')) { - // D - buttons |= 0x0008; // XINPUT_GAMEPAD_DPAD_RIGHT - } - if (IS_KEY_DOWN('S')) { - // S - buttons |= 0x0002; // XINPUT_GAMEPAD_DPAD_DOWN - } - if (IS_KEY_DOWN('W')) { - // W - buttons |= 0x0001; // XINPUT_GAMEPAD_DPAD_UP - } - } else { - // left stick - if (IS_KEY_DOWN('A')) { - // A - thumb_lx += SHRT_MIN; - } - if (IS_KEY_DOWN('D')) { - // D - thumb_lx += SHRT_MAX; - } - if (IS_KEY_DOWN('S')) { - // S - thumb_ly += SHRT_MIN; - } - if (IS_KEY_DOWN('W')) { - // W - thumb_ly += SHRT_MAX; - } - } - - if (IS_KEY_DOWN('F')) { - // F - buttons |= 0x0040; // XINPUT_GAMEPAD_LEFT_THUMB - } - - // Right stick - if (IS_KEY_DOWN(VK_UP)) { - // Up - thumb_ry += SHRT_MAX; - } - if (IS_KEY_DOWN(VK_DOWN)) { - // Down - thumb_ry += SHRT_MIN; - } - if (IS_KEY_DOWN(VK_RIGHT)) { - // Right - thumb_rx += SHRT_MAX; - } - if (IS_KEY_DOWN(VK_LEFT)) { - // Left - thumb_rx += SHRT_MIN; - } - - if (IS_KEY_DOWN('L')) { - // L - buttons |= 0x4000; // XINPUT_GAMEPAD_X - } - if (IS_KEY_DOWN(VK_OEM_7)) { - // ' - buttons |= 0x2000; // XINPUT_GAMEPAD_B - } - if (IS_KEY_DOWN(VK_OEM_1)) { - // ; - buttons |= 0x1000; // XINPUT_GAMEPAD_A - } - if (IS_KEY_DOWN('P')) { - // P - buttons |= 0x8000; // XINPUT_GAMEPAD_Y - } - - if (IS_KEY_DOWN('K')) { - // K - buttons |= 0x0080; // XINPUT_GAMEPAD_RIGHT_THUMB - } - - if (IS_KEY_DOWN('Q') || IS_KEY_DOWN('I')) { - // Q / I - left_trigger = 0xFF; - } - - if (IS_KEY_DOWN('E') || IS_KEY_DOWN('O')) { - // E / O - right_trigger = 0xFF; - } - - if (IS_KEY_DOWN('Z')) { - // Z - buttons |= 0x0020; // XINPUT_GAMEPAD_BACK - } - if (IS_KEY_DOWN('X')) { - // X - buttons |= 0x0010; // XINPUT_GAMEPAD_START - } - if (IS_KEY_DOWN('1')) { - // 1 - buttons |= 0x0100; // XINPUT_GAMEPAD_LEFT_SHOULDER - } - if (IS_KEY_DOWN('3')) { - // 3 - buttons |= 0x0200; // XINPUT_GAMEPAD_RIGHT_SHOULDER } } @@ -259,90 +271,13 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, key_events_.pop(); } - switch (evt.virtual_key) { - case ui::VirtualKey::kOem1: // ; - xinput_virtual_key = ui::VirtualKey::kXInputPadA; - break; - case ui::VirtualKey::kOem7: // ' - xinput_virtual_key = ui::VirtualKey::kXInputPadB; - break; - case ui::VirtualKey::kL: - xinput_virtual_key = ui::VirtualKey::kXInputPadX; - break; - case ui::VirtualKey::kP: - xinput_virtual_key = ui::VirtualKey::kXInputPadY; - break; - case ui::VirtualKey::k3: - xinput_virtual_key = ui::VirtualKey::kXInputPadRShoulder; - break; - case ui::VirtualKey::k1: - xinput_virtual_key = ui::VirtualKey::kXInputPadLShoulder; - break; - case ui::VirtualKey::kQ: - case ui::VirtualKey::kI: - xinput_virtual_key = ui::VirtualKey::kXInputPadLTrigger; - break; - case ui::VirtualKey::kE: - case ui::VirtualKey::kO: - xinput_virtual_key = ui::VirtualKey::kXInputPadRTrigger; - break; - case ui::VirtualKey::kX: - xinput_virtual_key = ui::VirtualKey::kXInputPadStart; - break; - case ui::VirtualKey::kZ: - xinput_virtual_key = ui::VirtualKey::kXInputPadBack; - break; - case ui::VirtualKey::kUp: - xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbUp; - break; - case ui::VirtualKey::kDown: - xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbDown; - break; - case ui::VirtualKey::kRight: - xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbRight; - break; - case ui::VirtualKey::kLeft: - xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbLeft; - break; - default: - // TODO(DrChat): Some other way to toggle this... - if (IS_KEY_TOGGLED(VK_CAPITAL) || IS_KEY_DOWN(VK_SHIFT)) { - // D-pad toggled. - switch (evt.virtual_key) { - case ui::VirtualKey::kW: - xinput_virtual_key = ui::VirtualKey::kXInputPadDpadUp; - break; - case ui::VirtualKey::kS: - xinput_virtual_key = ui::VirtualKey::kXInputPadDpadDown; - break; - case ui::VirtualKey::kA: - xinput_virtual_key = ui::VirtualKey::kXInputPadDpadLeft; - break; - case ui::VirtualKey::kD: - xinput_virtual_key = ui::VirtualKey::kXInputPadDpadRight; - break; - default: - break; - } - } else { - // Left thumbstick. - switch (evt.virtual_key) { - case ui::VirtualKey::kW: - xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbUp; - break; - case ui::VirtualKey::kS: - xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbDown; - break; - case ui::VirtualKey::kA: - xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbLeft; - break; - case ui::VirtualKey::kD: - xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbRight; - break; - default: - break; - } - } + bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT); + for (const KeyBinding& b : key_bindings_) { + if (b.input_key == evt.virtual_key && + ((b.lowercase == b.uppercase) || (b.lowercase && !capital) || + (b.uppercase && capital))) { + xinput_virtual_key = b.output_key; + } } if (xinput_virtual_key != ui::VirtualKey::kNone) { @@ -371,6 +306,29 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, return result; } +void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyDown(ui::KeyEvent& e) { + driver_.OnKey(e, true); +} + +void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyUp(ui::KeyEvent& e) { + driver_.OnKey(e, false); +} + +void WinKeyInputDriver::OnKey(ui::KeyEvent& e, bool is_down) { + if (!is_active()) { + return; + } + + KeyEvent key; + key.virtual_key = e.virtual_key(); + key.transition = is_down; + key.prev_state = e.prev_state(); + key.repeat_count = e.repeat_count(); + + auto global_lock = global_critical_region_.Acquire(); + key_events_.push(key); +} + } // namespace winkey } // namespace hid } // namespace xe diff --git a/src/xenia/hid/winkey/winkey_input_driver.h b/src/xenia/hid/winkey/winkey_input_driver.h index f015b7416..e11788acf 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.h +++ b/src/xenia/hid/winkey/winkey_input_driver.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -20,9 +20,9 @@ namespace xe { namespace hid { namespace winkey { -class WinKeyInputDriver : public InputDriver { +class WinKeyInputDriver final : public InputDriver { public: - explicit WinKeyInputDriver(xe::ui::Window* window); + explicit WinKeyInputDriver(xe::ui::Window* window, size_t window_z_order); ~WinKeyInputDriver() override; X_STATUS Setup() override; @@ -42,10 +42,38 @@ class WinKeyInputDriver : public InputDriver { bool prev_state = false; // down(true) or up(false) }; + struct KeyBinding { + ui::VirtualKey input_key = ui::VirtualKey::kNone; + ui::VirtualKey output_key = ui::VirtualKey::kNone; + bool uppercase = false; + bool lowercase = false; + }; + + class WinKeyWindowInputListener final : public ui::WindowInputListener { + public: + explicit WinKeyWindowInputListener(WinKeyInputDriver& driver) + : driver_(driver) {} + + void OnKeyDown(ui::KeyEvent& e) override; + void OnKeyUp(ui::KeyEvent& e) override; + + private: + WinKeyInputDriver& driver_; + }; + + void ParseKeyBinding(ui::VirtualKey virtual_key, + const std::string_view description, + const std::string_view binding); + + void OnKey(ui::KeyEvent& e, bool is_down); + + WinKeyWindowInputListener window_input_listener_; + xe::global_critical_region global_critical_region_; std::queue key_events_; + std::vector key_bindings_; - uint32_t packet_number_; + uint32_t packet_number_ = 1; }; } // namespace winkey diff --git a/src/xenia/hid/xinput/xinput_hid.cc b/src/xenia/hid/xinput/xinput_hid.cc index 093d266f0..21f4304f1 100644 --- a/src/xenia/hid/xinput/xinput_hid.cc +++ b/src/xenia/hid/xinput/xinput_hid.cc @@ -15,8 +15,9 @@ namespace xe { namespace hid { namespace xinput { -std::unique_ptr Create(xe::ui::Window* window) { - return std::make_unique(window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order) { + return std::make_unique(window, window_z_order); } } // namespace xinput diff --git a/src/xenia/hid/xinput/xinput_hid.h b/src/xenia/hid/xinput/xinput_hid.h index c295cb434..2c6cb231b 100644 --- a/src/xenia/hid/xinput/xinput_hid.h +++ b/src/xenia/hid/xinput/xinput_hid.h @@ -18,7 +18,8 @@ namespace xe { namespace hid { namespace xinput { -std::unique_ptr Create(xe::ui::Window* window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order); } // namespace xinput } // namespace hid diff --git a/src/xenia/hid/xinput/xinput_input_driver.cc b/src/xenia/hid/xinput/xinput_input_driver.cc index 830daa0e4..497d80089 100644 --- a/src/xenia/hid/xinput/xinput_input_driver.cc +++ b/src/xenia/hid/xinput/xinput_input_driver.cc @@ -21,8 +21,9 @@ namespace xe { namespace hid { namespace xinput { -XInputInputDriver::XInputInputDriver(xe::ui::Window* window) - : InputDriver(window), +XInputInputDriver::XInputInputDriver(xe::ui::Window* window, + size_t window_z_order) + : InputDriver(window, window_z_order), module_(nullptr), XInputGetCapabilities_(nullptr), XInputGetState_(nullptr), diff --git a/src/xenia/hid/xinput/xinput_input_driver.h b/src/xenia/hid/xinput/xinput_input_driver.h index dcde26197..b14113963 100644 --- a/src/xenia/hid/xinput/xinput_input_driver.h +++ b/src/xenia/hid/xinput/xinput_input_driver.h @@ -16,9 +16,9 @@ namespace xe { namespace hid { namespace xinput { -class XInputInputDriver : public InputDriver { +class XInputInputDriver final : public InputDriver { public: - explicit XInputInputDriver(xe::ui::Window* window); + explicit XInputInputDriver(xe::ui::Window* window, size_t window_z_order); ~XInputInputDriver() override; X_STATUS Setup() override; @@ -30,7 +30,7 @@ class XInputInputDriver : public InputDriver { X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags, X_INPUT_KEYSTROKE* out_keystroke) override; - protected: + private: void* module_; void* XInputGetCapabilities_; void* XInputGetState_; diff --git a/src/xenia/kernel/util/shim_utils.h b/src/xenia/kernel/util/shim_utils.h index 964845be9..0b6551615 100644 --- a/src/xenia/kernel/util/shim_utils.h +++ b/src/xenia/kernel/util/shim_utils.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -33,7 +33,7 @@ using PPCContext = xe::cpu::ppc::PPCContext; #define SHIM_SET_MAPPING(library_name, export_name, shim_data) \ export_resolver->SetFunctionMapping( \ library_name, ordinals::export_name, \ - (xe::cpu::xe_kernel_export_shim_fn)export_name##_shim); + (xe::cpu::xe_kernel_export_shim_fn)export_name##_entry); #define SHIM_MEM_ADDR(a) \ ((a) ? ppc_context->kernel_state->memory()->TranslateVirtual(a) : nullptr) @@ -324,15 +324,20 @@ class TypedPointerParam : public ParamBase { T* host_ptr_; }; -template class Result { public: - Result(T value) : value_(value) {} + virtual void Store(PPCContext* ppc_context) = 0; +}; + +template +class ResultBase : public Result { + public: + ResultBase(T value) : value_(value) {} void Store(PPCContext* ppc_context) { ppc_context->r[3] = uint64_t(int32_t(value_)); } - Result() = delete; - Result& operator=(const Result&) = delete; + ResultBase() = delete; + ResultBase& operator=(const ResultBase&) = delete; operator T() const { return value_; } private: @@ -361,10 +366,10 @@ using lpunknown_t = const shim::PointerParam&; template using pointer_t = const shim::TypedPointerParam&; -using int_result_t = shim::Result; -using dword_result_t = shim::Result; -using pointer_result_t = shim::Result; -using X_HRESULT_result_t = shim::Result; +using int_result_t = shim::ResultBase; +using dword_result_t = shim::ResultBase; +using pointer_result_t = shim::ResultBase; +using X_HRESULT_result_t = shim::ResultBase; // Exported from kernel_state.cc. KernelState* kernel_state(); @@ -453,7 +458,7 @@ inline void AppendParam(StringBuffer* string_buffer, inline void AppendParam(StringBuffer* string_buffer, pointer_t record) { string_buffer->AppendFormat("{:08X}({:08X})", record.guest_address(), - uint32_t(record->exception_code)); + uint32_t(record->code)); } template void AppendParam(StringBuffer* string_buffer, pointer_t param) { @@ -511,6 +516,11 @@ auto KernelTrampoline(F&& f, Tuple&& t, std::index_sequence) { template xe::cpu::Export* RegisterExport(R (*fn)(Ps&...), const char* name, xe::cpu::ExportTag::type tags) { + static_assert( + std::is_void::value || std::is_base_of::value, + "R must be void or derive from shim::Result"); + static_assert((std::is_base_of_v && ...), + "Ps must derive from shim::Param"); static const auto export_entry = new cpu::Export( ORDINAL, xe::cpu::Export::Type::kFunction, name, tags | xe::cpu::ExportTag::kImplemented | xe::cpu::ExportTag::kLog); @@ -559,11 +569,16 @@ using xe::cpu::ExportTag; const auto EXPORT_##module_name##_##name = RegisterExport_##module_name( \ xe::kernel::shim::RegisterExport< \ xe::kernel::shim::KernelModuleId::module_name, ordinals::name>( \ - &name, #name, \ + &name##_entry, #name, \ tags | (static_cast( \ xe::cpu::ExportCategory::category) \ << xe::cpu::ExportTag::CategoryShift))); +#define DECLARE_EMPTY_REGISTER_EXPORTS(module_name, group_name) \ + void xe::kernel::module_name::Register##group_name##Exports( \ + xe::cpu::ExportResolver* export_resolver, \ + xe::kernel::KernelState* kernel_state) {} + #define DECLARE_XAM_EXPORT_(name, category, tags) \ DECLARE_EXPORT(xam, name, category, tags) #define DECLARE_XAM_EXPORT1(name, category, tag) \ @@ -572,11 +587,17 @@ using xe::cpu::ExportTag; DECLARE_EXPORT(xam, name, category, \ xe::cpu::ExportTag::tag1 | xe::cpu::ExportTag::tag2) +#define DECLARE_XAM_EMPTY_REGISTER_EXPORTS(group_name) \ + DECLARE_EMPTY_REGISTER_EXPORTS(xam, group_name) + #define DECLARE_XBDM_EXPORT_(name, category, tags) \ DECLARE_EXPORT(xbdm, name, category, tags) #define DECLARE_XBDM_EXPORT1(name, category, tag) \ DECLARE_EXPORT(xbdm, name, category, xe::cpu::ExportTag::tag) +#define DECLARE_XBDM_EMPTY_REGISTER_EXPORTS(group_name) \ + DECLARE_EMPTY_REGISTER_EXPORTS(xbdm, group_name) + #define DECLARE_XBOXKRNL_EXPORT_(name, category, tags) \ DECLARE_EXPORT(xboxkrnl, name, category, tags) #define DECLARE_XBOXKRNL_EXPORT1(name, category, tag) \ @@ -593,6 +614,9 @@ using xe::cpu::ExportTag; xe::cpu::ExportTag::tag1 | xe::cpu::ExportTag::tag2 | \ xe::cpu::ExportTag::tag3 | xe::cpu::ExportTag::tag4) +#define DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(group_name) \ + DECLARE_EMPTY_REGISTER_EXPORTS(xboxkrnl, group_name) + } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xam/apps/xmp_app.cc b/src/xenia/kernel/xam/apps/xmp_app.cc index c492192ab..2f42c1a12 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.cc +++ b/src/xenia/kernel/xam/apps/xmp_app.cc @@ -21,11 +21,11 @@ namespace apps { XmpApp::XmpApp(KernelState* kernel_state) : App(kernel_state, 0xFA), state_(State::kIdle), - disabled_(0), + playback_client_(PlaybackClient::kTitle), playback_mode_(PlaybackMode::kUnknown), repeat_mode_(RepeatMode::kUnknown), unknown_flags_(0), - volume_(0.0f), + volume_(1.0f), active_playlist_(nullptr), active_song_index_(0), next_playlist_handle_(1), @@ -131,9 +131,8 @@ X_HRESULT XmpApp::XMPPlayTitlePlaylist(uint32_t playlist_handle, playlist = it->second; } - if (disabled_) { - // Ignored because we aren't enabled? - XELOGW("Ignoring XMPPlayTitlePlaylist because disabled"); + if (playback_client_ == PlaybackClient::kSystem) { + XELOGW("XMPPlayTitlePlaylist: System playback is enabled!"); return X_E_SUCCESS; } @@ -395,7 +394,7 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, struct { xe::be xmp_client; xe::be controller; - xe::be locked; + xe::be playback_client; }* args = memory_->TranslateVirtual(buffer_ptr); static_assert_size(decltype(*args), 12); @@ -403,13 +402,11 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, (args->xmp_client == 0x00000002 && args->controller == 0x00000000) || (args->xmp_client == 0x00000000 && args->controller == 0x00000001)); XELOGD("XMPSetPlaybackController({:08X}, {:08X})", - uint32_t(args->controller), uint32_t(args->locked)); + uint32_t(args->controller), uint32_t(args->playback_client)); - disabled_ = args->locked; - if (disabled_) { - XMPStop(0); - } - kernel_state_->BroadcastNotification(kMsgDisableChanged, disabled_); + playback_client_ = PlaybackClient(uint32_t(args->playback_client)); + kernel_state_->BroadcastNotification(kMsgPlaybackControllerChanged, + !args->playback_client); return X_E_SUCCESS; } case 0x0007001B: { diff --git a/src/xenia/kernel/xam/apps/xmp_app.h b/src/xenia/kernel/xam/apps/xmp_app.h index cb4966a00..6a365c2f2 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.h +++ b/src/xenia/kernel/xam/apps/xmp_app.h @@ -34,6 +34,10 @@ class XmpApp : public App { kPlaying = 1, kPaused = 2, }; + enum class PlaybackClient : uint32_t { + kSystem = 0, + kTitle = 1, + }; enum class PlaybackMode : uint32_t { // kInOrder = ?, kUnknown = 0, @@ -90,12 +94,12 @@ class XmpApp : public App { private: static const uint32_t kMsgStateChanged = 0x0A000001; static const uint32_t kMsgPlaybackBehaviorChanged = 0x0A000002; - static const uint32_t kMsgDisableChanged = 0x0A000003; + static const uint32_t kMsgPlaybackControllerChanged = 0x0A000003; void OnStateChanged(); State state_; - uint32_t disabled_; + PlaybackClient playback_client_; PlaybackMode playback_mode_; RepeatMode repeat_mode_; uint32_t unknown_flags_; diff --git a/src/xenia/kernel/xam/content_manager.cc b/src/xenia/kernel/xam/content_manager.cc index a4367a48b..883020ce9 100644 --- a/src/xenia/kernel/xam/content_manager.cc +++ b/src/xenia/kernel/xam/content_manager.cc @@ -245,7 +245,7 @@ X_RESULT ContentManager::DeleteContent(const XCONTENT_AGGREGATE_DATA& data) { } std::filesystem::path ContentManager::ResolveGameUserContentPath() { - auto title_id = fmt::format("{:8X}", kernel_state_->title_id()); + auto title_id = fmt::format("{:08X}", kernel_state_->title_id()); auto user_name = xe::to_path(kernel_state_->user_profile()->name()); // Per-game per-profile data location: diff --git a/src/xenia/kernel/xam/user_profile.h b/src/xenia/kernel/xam/user_profile.h index 82bb7b7a4..ad24b003d 100644 --- a/src/xenia/kernel/xam/user_profile.h +++ b/src/xenia/kernel/xam/user_profile.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -15,14 +15,69 @@ #include #include +#include "xenia/base/byte_stream.h" #include "xenia/xbox.h" namespace xe { namespace kernel { namespace xam { +struct X_USER_PROFILE_SETTING_DATA { + // UserProfile::Setting::Type. Appears to be 8-in-32 field, and the upper 24 + // are not always zeroed by the game. + uint8_t type; + uint8_t unk_1[3]; + xe::be unk_4; + // TODO(sabretooth): not sure if this is a union, but it seems likely. + // Haven't run into cases other than "binary data" yet. + union { + xe::be s32; + xe::be s64; + xe::be u32; + xe::be f64; + struct { + xe::be size; + xe::be ptr; + } unicode; + xe::be f32; + struct { + xe::be size; + xe::be ptr; + } binary; + xe::be filetime; + }; +}; +static_assert_size(X_USER_PROFILE_SETTING_DATA, 16); + +struct X_USER_PROFILE_SETTING { + xe::be from; + xe::be unk04; + union { + xe::be user_index; + xe::be xuid; + }; + xe::be setting_id; + xe::be unk14; + union { + uint8_t data_bytes[sizeof(X_USER_PROFILE_SETTING_DATA)]; + X_USER_PROFILE_SETTING_DATA data; + }; +}; +static_assert_size(X_USER_PROFILE_SETTING, 40); + class UserProfile { public: + class SettingByteStream : public ByteStream { + public: + SettingByteStream(uint32_t ptr, uint8_t* data, size_t data_length, + size_t offset = 0) + : ByteStream(data, data_length, offset), ptr_(ptr) {} + + uint32_t ptr() const { return static_cast(ptr_ + offset()); } + + private: + uint32_t ptr_; + }; struct Setting { enum class Type { CONTENT = 0, @@ -33,7 +88,7 @@ class UserProfile { FLOAT = 5, BINARY = 6, DATETIME = 7, - INVALID = 0xFF, + UNSET = 0xFF, }; union Key { uint32_t value; @@ -55,97 +110,77 @@ class UserProfile { size(size), is_set(is_set), loaded_title_id(0) {} - virtual size_t extra_size() const { return 0; } - virtual size_t Append(uint8_t* user_data, uint8_t* buffer, - uint32_t buffer_ptr, size_t buffer_offset) { - xe::store_and_swap(user_data + kTypeOffset, - static_cast(type)); - return buffer_offset; + virtual void Append(X_USER_PROFILE_SETTING_DATA* data, + SettingByteStream* stream) { + data->type = static_cast(type); } virtual std::vector Serialize() const { return std::vector(); } virtual void Deserialize(std::vector) {} bool is_title_specific() const { return (setting_id & 0x3F00) == 0x3F00; } - - protected: - const size_t kTypeOffset = 0; - const size_t kValueOffset = 8; - const size_t kPointerOffset = 12; }; struct Int32Setting : public Setting { Int32Setting(uint32_t setting_id, int32_t value) : Setting(setting_id, Type::INT32, 4, true), value(value) {} int32_t value; - size_t Append(uint8_t* user_data, uint8_t* buffer, uint32_t buffer_ptr, - size_t buffer_offset) override { - buffer_offset = - Setting::Append(user_data, buffer, buffer_ptr, buffer_offset); - xe::store_and_swap(user_data + kValueOffset, value); - return buffer_offset; + void Append(X_USER_PROFILE_SETTING_DATA* data, + SettingByteStream* stream) override { + Setting::Append(data, stream); + data->s32 = value; } }; struct Int64Setting : public Setting { Int64Setting(uint32_t setting_id, int64_t value) : Setting(setting_id, Type::INT64, 8, true), value(value) {} int64_t value; - size_t Append(uint8_t* user_data, uint8_t* buffer, uint32_t buffer_ptr, - size_t buffer_offset) override { - buffer_offset = - Setting::Append(user_data, buffer, buffer_ptr, buffer_offset); - xe::store_and_swap(user_data + kValueOffset, value); - return buffer_offset; + void Append(X_USER_PROFILE_SETTING_DATA* data, + SettingByteStream* stream) override { + Setting::Append(data, stream); + data->s64 = value; } }; struct DoubleSetting : public Setting { DoubleSetting(uint32_t setting_id, double value) : Setting(setting_id, Type::DOUBLE, 8, true), value(value) {} double value; - size_t Append(uint8_t* user_data, uint8_t* buffer, uint32_t buffer_ptr, - size_t buffer_offset) override { - buffer_offset = - Setting::Append(user_data, buffer, buffer_ptr, buffer_offset); - xe::store_and_swap(user_data + kValueOffset, value); - return buffer_offset; + void Append(X_USER_PROFILE_SETTING_DATA* data, + SettingByteStream* stream) override { + Setting::Append(data, stream); + data->f64 = value; } }; struct UnicodeSetting : public Setting { UnicodeSetting(uint32_t setting_id, const std::u16string& value) : Setting(setting_id, Type::WSTRING, 8, true), value(value) {} std::u16string value; - size_t extra_size() const override { - return value.empty() ? 0 : 2 * (static_cast(value.size()) + 1); - } - size_t Append(uint8_t* user_data, uint8_t* buffer, uint32_t buffer_ptr, - size_t buffer_offset) override { - buffer_offset = - Setting::Append(user_data, buffer, buffer_ptr, buffer_offset); - int32_t length; + void Append(X_USER_PROFILE_SETTING_DATA* data, + SettingByteStream* stream) override { + Setting::Append(data, stream); if (value.empty()) { - length = 0; - xe::store_and_swap(user_data + kValueOffset, 0); - xe::store_and_swap(user_data + kPointerOffset, 0); + data->unicode.size = 0; + data->unicode.ptr = 0; } else { - length = 2 * (static_cast(value.size()) + 1); - xe::store_and_swap(user_data + kValueOffset, length); - xe::store_and_swap( - user_data + kPointerOffset, - buffer_ptr + static_cast(buffer_offset)); - memcpy(buffer + buffer_offset, value.data(), length); + size_t count = value.size() + 1; + size_t size = 2 * count; + assert_true(size <= std::numeric_limits::max()); + data->unicode.size = static_cast(size); + data->unicode.ptr = stream->ptr(); + auto buffer = + reinterpret_cast(&stream->data()[stream->offset()]); + stream->Advance(size); + xe::copy_and_swap(buffer, (uint16_t*)value.data(), count); } - return buffer_offset + length; } }; struct FloatSetting : public Setting { FloatSetting(uint32_t setting_id, float value) : Setting(setting_id, Type::FLOAT, 4, true), value(value) {} float value; - size_t Append(uint8_t* user_data, uint8_t* buffer, uint32_t buffer_ptr, - size_t buffer_offset) override { - buffer_offset = - Setting::Append(user_data, buffer, buffer_ptr, buffer_offset); - xe::store_and_swap(user_data + kValueOffset, value); - return buffer_offset; + void Append(X_USER_PROFILE_SETTING_DATA* data, + SettingByteStream* stream) override { + Setting::Append(data, stream); + data->f32 = value; } }; struct BinarySetting : public Setting { @@ -154,27 +189,19 @@ class UserProfile { BinarySetting(uint32_t setting_id, const std::vector& value) : Setting(setting_id, Type::BINARY, 8, true), value(value) {} std::vector value; - size_t extra_size() const override { - return static_cast(value.size()); - } - size_t Append(uint8_t* user_data, uint8_t* buffer, uint32_t buffer_ptr, - size_t buffer_offset) override { - buffer_offset = - Setting::Append(user_data, buffer, buffer_ptr, buffer_offset); - int32_t length; + void Append(X_USER_PROFILE_SETTING_DATA* data, + SettingByteStream* stream) override { + Setting::Append(data, stream); if (value.empty()) { - length = 0; - xe::store_and_swap(user_data + kValueOffset, 0); - xe::store_and_swap(user_data + kPointerOffset, 0); + data->binary.size = 0; + data->binary.ptr = 0; } else { - length = static_cast(value.size()); - xe::store_and_swap(user_data + kValueOffset, length); - xe::store_and_swap( - user_data + kPointerOffset, - buffer_ptr + static_cast(buffer_offset)); - memcpy(buffer + buffer_offset, value.data(), length); + size_t size = value.size(); + assert_true(size <= std::numeric_limits::max()); + data->binary.size = static_cast(size); + data->binary.ptr = stream->ptr(); + stream->Write(value.data(), size); } - return buffer_offset + length; } std::vector Serialize() const override { return std::vector(value.data(), value.data() + value.size()); @@ -188,12 +215,10 @@ class UserProfile { DateTimeSetting(uint32_t setting_id, int64_t value) : Setting(setting_id, Type::DATETIME, 8, true), value(value) {} int64_t value; - size_t Append(uint8_t* user_data, uint8_t* buffer, uint32_t buffer_ptr, - size_t buffer_offset) override { - buffer_offset = - Setting::Append(user_data, buffer, buffer_ptr, buffer_offset); - xe::store_and_swap(user_data + kValueOffset, value); - return buffer_offset; + void Append(X_USER_PROFILE_SETTING_DATA* data, + SettingByteStream* stream) override { + Setting::Append(data, stream); + data->filetime = value; } }; diff --git a/src/xenia/kernel/xam/xam_avatar.cc b/src/xenia/kernel/xam/xam_avatar.cc index a949e91b2..c3c8917ff 100644 --- a/src/xenia/kernel/xam/xam_avatar.cc +++ b/src/xenia/kernel/xam/xam_avatar.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,7 +17,7 @@ namespace xe { namespace kernel { namespace xam { -dword_result_t XamAvatarInitialize( +dword_result_t XamAvatarInitialize_entry( dword_t unk1, // 1, 4, etc dword_t unk2, // 0 or 1 dword_t processor_number, // for thread creation? @@ -30,14 +30,13 @@ dword_result_t XamAvatarInitialize( } DECLARE_XAM_EXPORT1(XamAvatarInitialize, kAvatars, kStub); -void XamAvatarShutdown() { +void XamAvatarShutdown_entry() { // No-op. } DECLARE_XAM_EXPORT1(XamAvatarShutdown, kAvatars, kStub); -void RegisterAvatarExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Avatar); diff --git a/src/xenia/kernel/xam/xam_content.cc b/src/xenia/kernel/xam/xam_content.cc index dea81d46b..11a9cf52b 100644 --- a/src/xenia/kernel/xam/xam_content.cc +++ b/src/xenia/kernel/xam/xam_content.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -31,8 +31,8 @@ namespace xe { namespace kernel { namespace xam { -dword_result_t XamContentGetLicenseMask(lpdword_t mask_ptr, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentGetLicenseMask_entry(lpdword_t mask_ptr, + lpunknown_t overlapped_ptr) { // Each bit in the mask represents a granted license. Available licenses // seems to vary from game to game, but most appear to use bit 0 to indicate // if the game is purchased or not. @@ -48,9 +48,11 @@ dword_result_t XamContentGetLicenseMask(lpdword_t mask_ptr, } DECLARE_XAM_EXPORT2(XamContentGetLicenseMask, kContent, kStub, kHighFrequency); -dword_result_t XamContentResolve(dword_t user_index, lpvoid_t content_data_ptr, - lpunknown_t buffer_ptr, dword_t buffer_size, - dword_t unk1, dword_t unk2, dword_t unk3) { +dword_result_t XamContentResolve_entry(dword_t user_index, + lpvoid_t content_data_ptr, + lpunknown_t buffer_ptr, + dword_t buffer_size, dword_t unk1, + dword_t unk2, dword_t unk3) { auto content_data = content_data_ptr.as(); // Result of buffer_ptr is sent to RtlInitAnsiString. @@ -64,12 +66,10 @@ DECLARE_XAM_EXPORT1(XamContentResolve, kContent, kStub); // https://github.com/MrColdbird/gameservice/blob/master/ContentManager.cpp // https://github.com/LestaD/SourceEngine2007/blob/master/se2007/engine/xboxsystem.cpp#L499 -dword_result_t XamContentCreateEnumerator(dword_t user_index, dword_t device_id, - dword_t content_type, - dword_t content_flags, - dword_t items_per_enumerate, - lpdword_t buffer_size_ptr, - lpdword_t handle_out) { +dword_result_t XamContentCreateEnumerator_entry( + dword_t user_index, dword_t device_id, dword_t content_type, + dword_t content_flags, dword_t items_per_enumerate, + lpdword_t buffer_size_ptr, lpdword_t handle_out) { assert_not_null(handle_out); auto device_info = device_id == 0 ? nullptr : GetDummyDeviceInfo(device_id); @@ -226,12 +226,10 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name, } } -dword_result_t XamContentCreateEx(dword_t user_index, lpstring_t root_name, - lpvoid_t content_data_ptr, dword_t flags, - lpdword_t disposition_ptr, - lpdword_t license_mask_ptr, - dword_t cache_size, qword_t content_size, - lpvoid_t overlapped_ptr) { +dword_result_t XamContentCreateEx_entry( + dword_t user_index, lpstring_t root_name, lpvoid_t content_data_ptr, + dword_t flags, lpdword_t disposition_ptr, lpdword_t license_mask_ptr, + dword_t cache_size, qword_t content_size, lpvoid_t overlapped_ptr) { return xeXamContentCreate(user_index, root_name, content_data_ptr, sizeof(XCONTENT_DATA), flags, disposition_ptr, license_mask_ptr, cache_size, content_size, @@ -239,18 +237,18 @@ dword_result_t XamContentCreateEx(dword_t user_index, lpstring_t root_name, } DECLARE_XAM_EXPORT1(XamContentCreateEx, kContent, kImplemented); -dword_result_t XamContentCreate(dword_t user_index, lpstring_t root_name, - lpvoid_t content_data_ptr, dword_t flags, - lpdword_t disposition_ptr, - lpdword_t license_mask_ptr, - lpvoid_t overlapped_ptr) { +dword_result_t XamContentCreate_entry(dword_t user_index, lpstring_t root_name, + lpvoid_t content_data_ptr, dword_t flags, + lpdword_t disposition_ptr, + lpdword_t license_mask_ptr, + lpvoid_t overlapped_ptr) { return xeXamContentCreate(user_index, root_name, content_data_ptr, sizeof(XCONTENT_DATA), flags, disposition_ptr, license_mask_ptr, 0, 0, overlapped_ptr); } DECLARE_XAM_EXPORT1(XamContentCreate, kContent, kImplemented); -dword_result_t XamContentCreateInternal( +dword_result_t XamContentCreateInternal_entry( lpstring_t root_name, lpvoid_t content_data_ptr, dword_t flags, lpdword_t disposition_ptr, lpdword_t license_mask_ptr, dword_t cache_size, qword_t content_size, lpvoid_t overlapped_ptr) { @@ -261,18 +259,19 @@ dword_result_t XamContentCreateInternal( } DECLARE_XAM_EXPORT1(XamContentCreateInternal, kContent, kImplemented); -dword_result_t XamContentOpenFile(dword_t user_index, lpstring_t root_name, - lpstring_t path, dword_t flags, - lpdword_t disposition_ptr, - lpdword_t license_mask_ptr, - lpvoid_t overlapped_ptr) { +dword_result_t XamContentOpenFile_entry(dword_t user_index, + lpstring_t root_name, lpstring_t path, + dword_t flags, + lpdword_t disposition_ptr, + lpdword_t license_mask_ptr, + lpvoid_t overlapped_ptr) { // TODO(gibbed): arguments assumed based on XamContentCreate. return X_ERROR_FILE_NOT_FOUND; } DECLARE_XAM_EXPORT1(XamContentOpenFile, kContent, kStub); -dword_result_t XamContentFlush(lpstring_t root_name, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentFlush_entry(lpstring_t root_name, + lpunknown_t overlapped_ptr) { X_RESULT result = X_ERROR_SUCCESS; if (overlapped_ptr) { kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, result); @@ -283,8 +282,8 @@ dword_result_t XamContentFlush(lpstring_t root_name, } DECLARE_XAM_EXPORT1(XamContentFlush, kContent, kStub); -dword_result_t XamContentClose(lpstring_t root_name, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentClose_entry(lpstring_t root_name, + lpunknown_t overlapped_ptr) { // Closes a previously opened root from XamContentCreate*. auto result = kernel_state()->content_manager()->CloseContent(root_name.value()); @@ -298,11 +297,11 @@ dword_result_t XamContentClose(lpstring_t root_name, } DECLARE_XAM_EXPORT1(XamContentClose, kContent, kImplemented); -dword_result_t XamContentGetCreator(dword_t user_index, - lpvoid_t content_data_ptr, - lpdword_t is_creator_ptr, - lpqword_t creator_xuid_ptr, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentGetCreator_entry(dword_t user_index, + lpvoid_t content_data_ptr, + lpdword_t is_creator_ptr, + lpqword_t creator_xuid_ptr, + lpunknown_t overlapped_ptr) { auto result = X_ERROR_SUCCESS; XCONTENT_AGGREGATE_DATA content_data = *content_data_ptr.as(); @@ -336,11 +335,11 @@ dword_result_t XamContentGetCreator(dword_t user_index, } DECLARE_XAM_EXPORT1(XamContentGetCreator, kContent, kImplemented); -dword_result_t XamContentGetThumbnail(dword_t user_index, - lpvoid_t content_data_ptr, - lpvoid_t buffer_ptr, - lpdword_t buffer_size_ptr, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentGetThumbnail_entry(dword_t user_index, + lpvoid_t content_data_ptr, + lpvoid_t buffer_ptr, + lpdword_t buffer_size_ptr, + lpunknown_t overlapped_ptr) { assert_not_null(buffer_size_ptr); uint32_t buffer_size = *buffer_size_ptr; XCONTENT_AGGREGATE_DATA content_data = *content_data_ptr.as(); @@ -375,10 +374,11 @@ dword_result_t XamContentGetThumbnail(dword_t user_index, } DECLARE_XAM_EXPORT1(XamContentGetThumbnail, kContent, kImplemented); -dword_result_t XamContentSetThumbnail(dword_t user_index, - lpvoid_t content_data_ptr, - lpvoid_t buffer_ptr, dword_t buffer_size, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentSetThumbnail_entry(dword_t user_index, + lpvoid_t content_data_ptr, + lpvoid_t buffer_ptr, + dword_t buffer_size, + lpunknown_t overlapped_ptr) { XCONTENT_AGGREGATE_DATA content_data = *content_data_ptr.as(); // Buffer is PNG data. @@ -396,8 +396,9 @@ dword_result_t XamContentSetThumbnail(dword_t user_index, } DECLARE_XAM_EXPORT1(XamContentSetThumbnail, kContent, kImplemented); -dword_result_t XamContentDelete(dword_t user_index, lpvoid_t content_data_ptr, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentDelete_entry(dword_t user_index, + lpvoid_t content_data_ptr, + lpunknown_t overlapped_ptr) { XCONTENT_AGGREGATE_DATA content_data = *content_data_ptr.as(); auto result = kernel_state()->content_manager()->DeleteContent(content_data); @@ -411,17 +412,16 @@ dword_result_t XamContentDelete(dword_t user_index, lpvoid_t content_data_ptr, } DECLARE_XAM_EXPORT1(XamContentDelete, kContent, kImplemented); -dword_result_t XamContentDeleteInternal(lpvoid_t content_data_ptr, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentDeleteInternal_entry(lpvoid_t content_data_ptr, + lpunknown_t overlapped_ptr) { // INFO: Analysis of xam.xex shows that "internal" functions are wrappers with // 0xFE as user_index - return XamContentDelete(0xFE, content_data_ptr, overlapped_ptr); + return XamContentDelete_entry(0xFE, content_data_ptr, overlapped_ptr); } DECLARE_XAM_EXPORT1(XamContentDeleteInternal, kContent, kImplemented); -void RegisterContentExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Content); diff --git a/src/xenia/kernel/xam/xam_content_aggregate.cc b/src/xenia/kernel/xam/xam_content_aggregate.cc index 765619002..eb41c29f7 100644 --- a/src/xenia/kernel/xam/xam_content_aggregate.cc +++ b/src/xenia/kernel/xam/xam_content_aggregate.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -76,11 +76,11 @@ void AddODDContentTest(object_ref> e, } } -dword_result_t XamContentAggregateCreateEnumerator(qword_t xuid, - dword_t device_id, - dword_t content_type, - unknown_t unk3, - lpdword_t handle_out) { +dword_result_t XamContentAggregateCreateEnumerator_entry(qword_t xuid, + dword_t device_id, + dword_t content_type, + unknown_t unk3, + lpdword_t handle_out) { assert_not_null(handle_out); auto device_info = device_id == 0 ? nullptr : GetDummyDeviceInfo(device_id); @@ -139,9 +139,8 @@ dword_result_t XamContentAggregateCreateEnumerator(qword_t xuid, } DECLARE_XAM_EXPORT1(XamContentAggregateCreateEnumerator, kContent, kStub); -void RegisterContentAggregateExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(ContentAggregate); diff --git a/src/xenia/kernel/xam/xam_content_device.cc b/src/xenia/kernel/xam/xam_content_device.cc index e4312de95..7abe02123 100644 --- a/src/xenia/kernel/xam/xam_content_device.cc +++ b/src/xenia/kernel/xam/xam_content_device.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -59,9 +59,9 @@ const DummyDeviceInfo* GetDummyDeviceInfo(uint32_t device_id) { return it == end ? nullptr : *it; } -dword_result_t XamContentGetDeviceName(dword_t device_id, - lpu16string_t name_buffer, - dword_t name_capacity) { +dword_result_t XamContentGetDeviceName_entry(dword_t device_id, + lpu16string_t name_buffer, + dword_t name_capacity) { auto device_info = GetDummyDeviceInfo(device_id); if (device_info == nullptr) { return X_ERROR_DEVICE_NOT_CONNECTED; @@ -75,8 +75,8 @@ dword_result_t XamContentGetDeviceName(dword_t device_id, } DECLARE_XAM_EXPORT1(XamContentGetDeviceName, kContent, kImplemented); -dword_result_t XamContentGetDeviceState(dword_t device_id, - lpunknown_t overlapped_ptr) { +dword_result_t XamContentGetDeviceState_entry(dword_t device_id, + lpunknown_t overlapped_ptr) { auto device_info = GetDummyDeviceInfo(device_id); if (device_info == nullptr) { if (overlapped_ptr) { @@ -110,7 +110,7 @@ typedef struct { } X_CONTENT_DEVICE_DATA; static_assert_size(X_CONTENT_DEVICE_DATA, 0x50); -dword_result_t XamContentGetDeviceData( +dword_result_t XamContentGetDeviceData_entry( dword_t device_id, pointer_t device_data) { auto device_info = GetDummyDeviceInfo(device_id); if (device_info == nullptr) { @@ -128,11 +128,11 @@ dword_result_t XamContentGetDeviceData( } DECLARE_XAM_EXPORT1(XamContentGetDeviceData, kContent, kImplemented); -dword_result_t XamContentCreateDeviceEnumerator(dword_t content_type, - dword_t content_flags, - dword_t max_count, - lpdword_t buffer_size_ptr, - lpdword_t handle_out) { +dword_result_t XamContentCreateDeviceEnumerator_entry(dword_t content_type, + dword_t content_flags, + dword_t max_count, + lpdword_t buffer_size_ptr, + lpdword_t handle_out) { assert_not_null(handle_out); if (buffer_size_ptr) { @@ -167,9 +167,8 @@ dword_result_t XamContentCreateDeviceEnumerator(dword_t content_type, } DECLARE_XAM_EXPORT1(XamContentCreateDeviceEnumerator, kNone, kImplemented); -void RegisterContentDeviceExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(ContentDevice); diff --git a/src/xenia/kernel/xam/xam_enum.cc b/src/xenia/kernel/xam/xam_enum.cc index 396d08dd7..9f5c08bb4 100644 --- a/src/xenia/kernel/xam/xam_enum.cc +++ b/src/xenia/kernel/xam/xam_enum.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -69,9 +69,10 @@ uint32_t xeXamEnumerate(uint32_t handle, uint32_t flags, lpvoid_t buffer_ptr, } } -dword_result_t XamEnumerate(dword_t handle, dword_t flags, lpvoid_t buffer, - dword_t buffer_length, lpdword_t items_returned, - pointer_t overlapped) { +dword_result_t XamEnumerate_entry(dword_t handle, dword_t flags, + lpvoid_t buffer, dword_t buffer_length, + lpdword_t items_returned, + pointer_t overlapped) { uint32_t dummy; auto result = xeXamEnumerate(handle, flags, buffer, buffer_length, !overlapped ? &dummy : nullptr, overlapped); @@ -82,16 +83,16 @@ dword_result_t XamEnumerate(dword_t handle, dword_t flags, lpvoid_t buffer, } DECLARE_XAM_EXPORT1(XamEnumerate, kNone, kImplemented); -dword_result_t XamCreateEnumeratorHandle(unknown_t unk1, unknown_t unk2, - unknown_t unk3, unknown_t unk4, - unknown_t unk5, unknown_t unk6, - unknown_t unk7, unknown_t unk8) { +dword_result_t XamCreateEnumeratorHandle_entry(unknown_t unk1, unknown_t unk2, + unknown_t unk3, unknown_t unk4, + unknown_t unk5, unknown_t unk6, + unknown_t unk7, unknown_t unk8) { return X_ERROR_INVALID_PARAMETER; } DECLARE_XAM_EXPORT1(XamCreateEnumeratorHandle, kNone, kStub); -dword_result_t XamGetPrivateEnumStructureFromHandle(dword_t handle, - lpdword_t out_object_ptr) { +dword_result_t XamGetPrivateEnumStructureFromHandle_entry( + dword_t handle, lpdword_t out_object_ptr) { auto e = kernel_state()->object_table()->LookupObject(handle); if (!e) { return X_STATUS_INVALID_HANDLE; @@ -109,9 +110,8 @@ dword_result_t XamGetPrivateEnumStructureFromHandle(dword_t handle, } DECLARE_XAM_EXPORT1(XamGetPrivateEnumStructureFromHandle, kNone, kStub); -void RegisterEnumExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Enum); diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index f697ff658..0bfe7c97b 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -28,7 +28,7 @@ namespace xe { namespace kernel { namespace xam { -dword_result_t XamFeatureEnabled(dword_t unk) { return 0; } +dword_result_t XamFeatureEnabled_entry(dword_t unk) { return 0; } DECLARE_XAM_EXPORT1(XamFeatureEnabled, kNone, kStub); // Empty stub schema binary. @@ -39,7 +39,7 @@ uint8_t schema_bin[] = { 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, }; -dword_result_t XamGetOnlineSchema() { +dword_result_t XamGetOnlineSchema_entry() { static uint32_t schema_guest = 0; if (!schema_guest) { @@ -70,8 +70,8 @@ static SYSTEMTIME xeGetLocalSystemTime(uint64_t filetime) { } #endif -void XamFormatDateString(dword_t unk, qword_t filetime, lpvoid_t output_buffer, - dword_t output_count) { +void XamFormatDateString_entry(dword_t unk, qword_t filetime, + lpvoid_t output_buffer, dword_t output_count) { std::memset(output_buffer, 0, output_count * sizeof(char16_t)); // TODO: implement this for other platforms @@ -87,8 +87,8 @@ void XamFormatDateString(dword_t unk, qword_t filetime, lpvoid_t output_buffer, } DECLARE_XAM_EXPORT1(XamFormatDateString, kNone, kImplemented); -void XamFormatTimeString(dword_t unk, qword_t filetime, lpvoid_t output_buffer, - dword_t output_count) { +void XamFormatTimeString_entry(dword_t unk, qword_t filetime, + lpvoid_t output_buffer, dword_t output_count) { std::memset(output_buffer, 0, output_count * sizeof(char16_t)); // TODO: implement this for other platforms @@ -124,18 +124,19 @@ dword_result_t keXamBuildResourceLocator(uint64_t module, return 0; } -dword_result_t XamBuildResourceLocator(qword_t module, lpu16string_t container, - lpu16string_t resource, - lpvoid_t buffer_ptr, - dword_t buffer_count) { +dword_result_t XamBuildResourceLocator_entry(qword_t module, + lpu16string_t container, + lpu16string_t resource, + lpvoid_t buffer_ptr, + dword_t buffer_count) { return keXamBuildResourceLocator(module, container.value(), resource.value(), buffer_ptr, buffer_count); } DECLARE_XAM_EXPORT1(XamBuildResourceLocator, kNone, kImplemented); -dword_result_t XamBuildGamercardResourceLocator(lpu16string_t filename, - lpvoid_t buffer_ptr, - dword_t buffer_count) { +dword_result_t XamBuildGamercardResourceLocator_entry(lpu16string_t filename, + lpvoid_t buffer_ptr, + dword_t buffer_count) { // On an actual xbox these funcs would return a locator to xam.xex resources, // but for Xenia we can return a locator to the resources as local files. (big // thanks to MS for letting XamBuildResourceLocator return local file @@ -149,32 +150,32 @@ dword_result_t XamBuildGamercardResourceLocator(lpu16string_t filename, } DECLARE_XAM_EXPORT1(XamBuildGamercardResourceLocator, kNone, kImplemented); -dword_result_t XamBuildSharedSystemResourceLocator(lpu16string_t filename, - lpvoid_t buffer_ptr, - dword_t buffer_count) { +dword_result_t XamBuildSharedSystemResourceLocator_entry(lpu16string_t filename, + lpvoid_t buffer_ptr, + dword_t buffer_count) { // see notes inside XamBuildGamercardResourceLocator above return keXamBuildResourceLocator(0, u"shrdres", filename.value(), buffer_ptr, buffer_count); } DECLARE_XAM_EXPORT1(XamBuildSharedSystemResourceLocator, kNone, kImplemented); -dword_result_t XamBuildLegacySystemResourceLocator(lpu16string_t filename, - lpvoid_t buffer_ptr, - dword_t buffer_count) { - return XamBuildSharedSystemResourceLocator(filename, buffer_ptr, - buffer_count); +dword_result_t XamBuildLegacySystemResourceLocator_entry(lpu16string_t filename, + lpvoid_t buffer_ptr, + dword_t buffer_count) { + return XamBuildSharedSystemResourceLocator_entry(filename, buffer_ptr, + buffer_count); } DECLARE_XAM_EXPORT1(XamBuildLegacySystemResourceLocator, kNone, kImplemented); -dword_result_t XamBuildXamResourceLocator(lpu16string_t filename, - lpvoid_t buffer_ptr, - dword_t buffer_count) { +dword_result_t XamBuildXamResourceLocator_entry(lpu16string_t filename, + lpvoid_t buffer_ptr, + dword_t buffer_count) { return keXamBuildResourceLocator(0, u"xam", filename.value(), buffer_ptr, buffer_count); } DECLARE_XAM_EXPORT1(XamBuildXamResourceLocator, kNone, kImplemented); -dword_result_t XamGetSystemVersion() { +dword_result_t XamGetSystemVersion_entry() { // eh, just picking one. If we go too low we may break new games, but // this value seems to be used for conditionally loading symbols and if // we pretend to be old we have less to worry with implementing. @@ -184,12 +185,12 @@ dword_result_t XamGetSystemVersion() { } DECLARE_XAM_EXPORT1(XamGetSystemVersion, kNone, kStub); -void XCustomRegisterDynamicActions() { +void XCustomRegisterDynamicActions_entry() { // ??? } DECLARE_XAM_EXPORT1(XCustomRegisterDynamicActions, kNone, kStub); -dword_result_t XGetAVPack() { +dword_result_t XGetAVPack_entry() { // DWORD // Not sure what the values are for this, but 6 is VGA. // Other likely values are 3/4/8 for HDMI or something. @@ -201,10 +202,10 @@ DECLARE_XAM_EXPORT1(XGetAVPack, kNone, kStub); uint32_t xeXGetGameRegion() { return 0xFFFFu; } -dword_result_t XGetGameRegion() { return xeXGetGameRegion(); } +dword_result_t XGetGameRegion_entry() { return xeXGetGameRegion(); } DECLARE_XAM_EXPORT1(XGetGameRegion, kNone, kStub); -dword_result_t XGetLanguage() { +dword_result_t XGetLanguage_entry() { auto desired_language = XLanguage::kEnglish; // Switch the language based on game region. @@ -221,7 +222,7 @@ dword_result_t XGetLanguage() { } DECLARE_XAM_EXPORT1(XGetLanguage, kNone, kImplemented); -dword_result_t XamGetExecutionId(lpdword_t info_ptr) { +dword_result_t XamGetExecutionId_entry(lpdword_t info_ptr) { auto module = kernel_state()->GetExecutableModule(); assert_not_null(module); @@ -238,7 +239,7 @@ dword_result_t XamGetExecutionId(lpdword_t info_ptr) { } DECLARE_XAM_EXPORT1(XamGetExecutionId, kNone, kImplemented); -dword_result_t XamLoaderSetLaunchData(lpvoid_t data, dword_t size) { +dword_result_t XamLoaderSetLaunchData_entry(lpvoid_t data, dword_t size) { auto xam = kernel_state()->GetKernelModule("xam.xex"); auto& loader_data = xam->loader_data(); loader_data.launch_data_present = size ? true : false; @@ -248,7 +249,7 @@ dword_result_t XamLoaderSetLaunchData(lpvoid_t data, dword_t size) { } DECLARE_XAM_EXPORT1(XamLoaderSetLaunchData, kNone, kSketchy); -dword_result_t XamLoaderGetLaunchDataSize(lpdword_t size_ptr) { +dword_result_t XamLoaderGetLaunchDataSize_entry(lpdword_t size_ptr) { if (!size_ptr) { return X_ERROR_INVALID_PARAMETER; } @@ -265,8 +266,8 @@ dword_result_t XamLoaderGetLaunchDataSize(lpdword_t size_ptr) { } DECLARE_XAM_EXPORT1(XamLoaderGetLaunchDataSize, kNone, kSketchy); -dword_result_t XamLoaderGetLaunchData(lpvoid_t buffer_ptr, - dword_t buffer_size) { +dword_result_t XamLoaderGetLaunchData_entry(lpvoid_t buffer_ptr, + dword_t buffer_size) { auto xam = kernel_state()->GetKernelModule("xam.xex"); auto& loader_data = xam->loader_data(); if (!loader_data.launch_data_present) { @@ -280,7 +281,7 @@ dword_result_t XamLoaderGetLaunchData(lpvoid_t buffer_ptr, } DECLARE_XAM_EXPORT1(XamLoaderGetLaunchData, kNone, kSketchy); -void XamLoaderLaunchTitle(lpstring_t raw_name_ptr, dword_t flags) { +void XamLoaderLaunchTitle_entry(lpstring_t raw_name_ptr, dword_t flags) { auto xam = kernel_state()->GetKernelModule("xam.xex"); auto& loader_data = xam->loader_data(); @@ -309,13 +310,13 @@ void XamLoaderLaunchTitle(lpstring_t raw_name_ptr, dword_t flags) { } DECLARE_XAM_EXPORT1(XamLoaderLaunchTitle, kNone, kSketchy); -void XamLoaderTerminateTitle() { +void XamLoaderTerminateTitle_entry() { // This function does not return. kernel_state()->TerminateTitle(); } DECLARE_XAM_EXPORT1(XamLoaderTerminateTitle, kNone, kSketchy); -dword_result_t XamAlloc(dword_t unk, dword_t size, lpdword_t out_ptr) { +dword_result_t XamAlloc_entry(dword_t unk, dword_t size, lpdword_t out_ptr) { assert_true(unk == 0); // Allocate from the heap. Not sure why XAM does this specially, perhaps @@ -327,22 +328,22 @@ dword_result_t XamAlloc(dword_t unk, dword_t size, lpdword_t out_ptr) { } DECLARE_XAM_EXPORT1(XamAlloc, kMemory, kImplemented); -dword_result_t XamFree(lpdword_t ptr) { +dword_result_t XamFree_entry(lpdword_t ptr) { kernel_state()->memory()->SystemHeapFree(ptr.guest_address()); return X_ERROR_SUCCESS; } DECLARE_XAM_EXPORT1(XamFree, kMemory, kImplemented); -dword_result_t XamQueryLiveHiveW(lpu16string_t name, lpvoid_t out_buf, - dword_t out_size, dword_t type /* guess */) { +dword_result_t XamQueryLiveHiveW_entry(lpu16string_t name, lpvoid_t out_buf, + dword_t out_size, + dword_t type /* guess */) { return X_STATUS_INVALID_PARAMETER_1; } DECLARE_XAM_EXPORT1(XamQueryLiveHiveW, kNone, kStub); -void RegisterInfoExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Info); diff --git a/src/xenia/kernel/xam/xam_input.cc b/src/xenia/kernel/xam/xam_input.cc index 7aead257d..2d177e98b 100644 --- a/src/xenia/kernel/xam/xam_input.cc +++ b/src/xenia/kernel/xam/xam_input.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -28,19 +28,20 @@ using xe::hid::X_INPUT_VIBRATION; constexpr uint32_t XINPUT_FLAG_GAMEPAD = 0x01; constexpr uint32_t XINPUT_FLAG_ANY_USER = 1 << 30; -void XamResetInactivity() { +void XamResetInactivity_entry() { // Do we need to do anything? } DECLARE_XAM_EXPORT1(XamResetInactivity, kInput, kStub); -dword_result_t XamEnableInactivityProcessing(dword_t unk, dword_t enable) { +dword_result_t XamEnableInactivityProcessing_entry(dword_t unk, + dword_t enable) { return X_ERROR_SUCCESS; } DECLARE_XAM_EXPORT1(XamEnableInactivityProcessing, kInput, kStub); // https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetcapabilities(v=vs.85).aspx -dword_result_t XamInputGetCapabilities(dword_t user_index, dword_t flags, - pointer_t caps) { +dword_result_t XamInputGetCapabilities_entry( + dword_t user_index, dword_t flags, pointer_t caps) { if (!caps) { return X_ERROR_BAD_ARGUMENTS; } @@ -61,9 +62,9 @@ dword_result_t XamInputGetCapabilities(dword_t user_index, dword_t flags, } DECLARE_XAM_EXPORT1(XamInputGetCapabilities, kInput, kSketchy); -dword_result_t XamInputGetCapabilitiesEx(dword_t unk, dword_t user_index, - dword_t flags, - pointer_t caps) { +dword_result_t XamInputGetCapabilitiesEx_entry( + dword_t unk, dword_t user_index, dword_t flags, + pointer_t caps) { if (!caps) { return X_ERROR_BAD_ARGUMENTS; } @@ -85,8 +86,8 @@ dword_result_t XamInputGetCapabilitiesEx(dword_t unk, dword_t user_index, DECLARE_XAM_EXPORT1(XamInputGetCapabilitiesEx, kInput, kSketchy); // https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetstate(v=vs.85).aspx -dword_result_t XamInputGetState(dword_t user_index, dword_t flags, - pointer_t input_state) { +dword_result_t XamInputGetState_entry(dword_t user_index, dword_t flags, + pointer_t input_state) { // Games call this with a NULL state ptr, probably as a query. if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0) { @@ -103,11 +104,11 @@ dword_result_t XamInputGetState(dword_t user_index, dword_t flags, auto input_system = kernel_state()->emulator()->input_system(); return input_system->GetState(user_index, input_state); } -DECLARE_XAM_EXPORT1(XamInputGetState, kInput, kImplemented); +DECLARE_XAM_EXPORT2(XamInputGetState, kInput, kImplemented, kHighFrequency); // https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputsetstate(v=vs.85).aspx -dword_result_t XamInputSetState(dword_t user_index, dword_t unk, - pointer_t vibration) { +dword_result_t XamInputSetState_entry(dword_t user_index, dword_t unk, + pointer_t vibration) { if (!vibration) { return X_ERROR_BAD_ARGUMENTS; } @@ -124,8 +125,8 @@ dword_result_t XamInputSetState(dword_t user_index, dword_t unk, DECLARE_XAM_EXPORT1(XamInputSetState, kInput, kImplemented); // https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetkeystroke(v=vs.85).aspx -dword_result_t XamInputGetKeystroke(dword_t user_index, dword_t flags, - pointer_t keystroke) { +dword_result_t XamInputGetKeystroke_entry( + dword_t user_index, dword_t flags, pointer_t keystroke) { // https://github.com/CodeAsm/ffplay360/blob/master/Common/AtgXime.cpp // user index = index or XUSER_INDEX_ANY // flags = XINPUT_FLAG_GAMEPAD (| _ANYUSER | _ANYDEVICE) @@ -151,8 +152,9 @@ dword_result_t XamInputGetKeystroke(dword_t user_index, dword_t flags, DECLARE_XAM_EXPORT1(XamInputGetKeystroke, kInput, kImplemented); // Same as non-ex, just takes a pointer to user index. -dword_result_t XamInputGetKeystrokeEx(lpdword_t user_index_ptr, dword_t flags, - pointer_t keystroke) { +dword_result_t XamInputGetKeystrokeEx_entry( + lpdword_t user_index_ptr, dword_t flags, + pointer_t keystroke) { if (!keystroke) { return X_ERROR_BAD_ARGUMENTS; } @@ -177,8 +179,9 @@ dword_result_t XamInputGetKeystrokeEx(lpdword_t user_index_ptr, dword_t flags, } DECLARE_XAM_EXPORT1(XamInputGetKeystrokeEx, kInput, kImplemented); -X_HRESULT_result_t XamUserGetDeviceContext(dword_t user_index, dword_t unk, - lpdword_t out_ptr) { +X_HRESULT_result_t XamUserGetDeviceContext_entry(dword_t user_index, + dword_t unk, + lpdword_t out_ptr) { // Games check the result - usually with some masking. // If this function fails they assume zero, so let's fail AND // set zero just to be safe. @@ -191,9 +194,8 @@ X_HRESULT_result_t XamUserGetDeviceContext(dword_t user_index, dword_t unk, } DECLARE_XAM_EXPORT1(XamUserGetDeviceContext, kInput, kStub); -void RegisterInputExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Input); diff --git a/src/xenia/kernel/xam/xam_locale.cc b/src/xenia/kernel/xam/xam_locale.cc index 880e5c003..e45c771ad 100644 --- a/src/xenia/kernel/xam/xam_locale.cc +++ b/src/xenia/kernel/xam/xam_locale.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -226,16 +226,19 @@ uint8_t xeXamGetLocale() { return xeXamGetLocaleEx(111, 43); } // Exports. -dword_result_t XamGetLocale() { return xeXamGetLocale(); } +dword_result_t XamGetLocale_entry() { + return static_cast(xeXamGetLocale()); +} DECLARE_XAM_EXPORT1(XamGetLocale, kLocale, kImplemented); -dword_result_t XamGetOnlineCountryFromLocale(dword_t id) { +dword_result_t XamGetOnlineCountryFromLocale_entry(dword_t id) { return xeXamGetOnlineCountryFromLocale(id); } DECLARE_XAM_EXPORT1(XamGetOnlineCountryFromLocale, kLocale, kImplemented); -dword_result_t XamGetOnlineCountryString(dword_t id, dword_t buffer_length, - lpu16string_t buffer) { +dword_result_t XamGetOnlineCountryString_entry(dword_t id, + dword_t buffer_length, + lpu16string_t buffer) { if (buffer_length >= 0x80000000u) { return X_E_INVALIDARG; } @@ -256,8 +259,8 @@ dword_result_t XamGetOnlineCountryString(dword_t id, dword_t buffer_length, } DECLARE_XAM_EXPORT1(XamGetOnlineCountryString, kLocale, kImplemented); -dword_result_t XamGetCountryString(dword_t id, dword_t buffer_length, - lpu16string_t buffer) { +dword_result_t XamGetCountryString_entry(dword_t id, dword_t buffer_length, + lpu16string_t buffer) { if (buffer_length >= 0x80000000u) { return X_E_INVALIDARG; } @@ -278,8 +281,8 @@ dword_result_t XamGetCountryString(dword_t id, dword_t buffer_length, } DECLARE_XAM_EXPORT1(XamGetCountryString, kLocale, kImplemented); -dword_result_t XamGetLanguageString(dword_t id, dword_t buffer_length, - lpu16string_t buffer) { +dword_result_t XamGetLanguageString_entry(dword_t id, dword_t buffer_length, + lpu16string_t buffer) { if (buffer_length >= 0x80000000u) { return X_E_INVALIDARG; } @@ -300,10 +303,10 @@ dword_result_t XamGetLanguageString(dword_t id, dword_t buffer_length, } DECLARE_XAM_EXPORT1(XamGetLanguageString, kLocale, kImplemented); -dword_result_t XamGetLanguageLocaleString(dword_t language_id, - dword_t locale_id, - dword_t buffer_length, - lpu16string_t buffer) { +dword_result_t XamGetLanguageLocaleString_entry(dword_t language_id, + dword_t locale_id, + dword_t buffer_length, + lpu16string_t buffer) { if (buffer_length >= 0x80000000u) { return X_E_INVALIDARG; } @@ -330,10 +333,9 @@ dword_result_t XamGetLanguageLocaleString(dword_t language_id, } DECLARE_XAM_EXPORT1(XamGetLanguageLocaleString, kLocale, kImplemented); -dword_result_t XamGetOnlineLanguageAndCountryString(dword_t language_id, - dword_t country_id, - dword_t buffer_length, - lpu16string_t buffer) { +dword_result_t XamGetOnlineLanguageAndCountryString_entry( + dword_t language_id, dword_t country_id, dword_t buffer_length, + lpu16string_t buffer) { if (buffer_length >= 0x80000000u) { return X_E_INVALIDARG; } @@ -363,8 +365,8 @@ dword_result_t XamGetOnlineLanguageAndCountryString(dword_t language_id, DECLARE_XAM_EXPORT1(XamGetOnlineLanguageAndCountryString, kLocale, kImplemented); -dword_result_t XamGetLocaleString(dword_t id, dword_t buffer_length, - lpu16string_t buffer) { +dword_result_t XamGetLocaleString_entry(dword_t id, dword_t buffer_length, + lpu16string_t buffer) { if (buffer_length >= 0x80000000u) { return X_E_INVALIDARG; } @@ -385,18 +387,19 @@ dword_result_t XamGetLocaleString(dword_t id, dword_t buffer_length, } DECLARE_XAM_EXPORT1(XamGetLocaleString, kLocale, kImplemented); -dword_result_t XamGetLocaleFromOnlineCountry(dword_t id) { +dword_result_t XamGetLocaleFromOnlineCountry_entry(dword_t id) { return xeXamGetLocaleFromOnlineCountry(static_cast(id)); } DECLARE_XAM_EXPORT1(XamGetLocaleFromOnlineCountry, kLocale, kImplemented); -dword_result_t XamGetLanguageFromOnlineLanguage(dword_t id) { +dword_result_t XamGetLanguageFromOnlineLanguage_entry(dword_t id) { return xeXamGetLanguageFromOnlineLanguage(static_cast(id)); } DECLARE_XAM_EXPORT1(XamGetLanguageFromOnlineLanguage, kLocale, kImplemented); -dword_result_t XamGetOnlineLanguageString(dword_t id, dword_t buffer_length, - lpu16string_t buffer) { +dword_result_t XamGetOnlineLanguageString_entry(dword_t id, + dword_t buffer_length, + lpu16string_t buffer) { if (buffer_length >= 0x80000000u) { return X_E_INVALIDARG; } @@ -417,12 +420,13 @@ dword_result_t XamGetOnlineLanguageString(dword_t id, dword_t buffer_length, } DECLARE_XAM_EXPORT1(XamGetOnlineLanguageString, kLocale, kImplemented); -dword_result_t XamGetCountryFromOnlineCountry(dword_t id) { +dword_result_t XamGetCountryFromOnlineCountry_entry(dword_t id) { return xeXamGetCountryFromOnlineCountry(static_cast(id)); } DECLARE_XAM_EXPORT1(XamGetCountryFromOnlineCountry, kLocale, kImplemented); -dword_result_t XamGetLocaleEx(dword_t max_country_id, dword_t max_locale_id) { +dword_result_t XamGetLocaleEx_entry(dword_t max_country_id, + dword_t max_locale_id) { return xeXamGetLocaleEx(static_cast(max_country_id), static_cast(max_locale_id)); } @@ -432,5 +436,4 @@ DECLARE_XAM_EXPORT1(XamGetLocaleEx, kLocale, kImplemented); } // namespace kernel } // namespace xe -void xe::kernel::xam::RegisterLocaleExports( - xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {} +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Locale); diff --git a/src/xenia/kernel/xam/xam_module.cc b/src/xenia/kernel/xam/xam_module.cc index 7689d3bf8..a94b1d6ef 100644 --- a/src/xenia/kernel/xam/xam_module.cc +++ b/src/xenia/kernel/xam/xam_module.cc @@ -27,6 +27,7 @@ XamModule::XamModule(Emulator* emulator, KernelState* kernel_state) : KernelModule(kernel_state, "xe:\\xam.xex"), loader_data_() { RegisterExportTable(export_resolver_); + // Register all exported functions. #define XE_MODULE_EXPORT_GROUP(m, n) \ Register##n##Exports(export_resolver_, kernel_state_); #include "xam_module_export_groups.inc" diff --git a/src/xenia/kernel/xam/xam_msg.cc b/src/xenia/kernel/xam/xam_msg.cc index aedac0573..3a1b83c3f 100644 --- a/src/xenia/kernel/xam/xam_msg.cc +++ b/src/xenia/kernel/xam/xam_msg.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -20,8 +20,8 @@ namespace xe { namespace kernel { namespace xam { -dword_result_t XMsgInProcessCall(dword_t app, dword_t message, dword_t arg1, - dword_t arg2) { +dword_result_t XMsgInProcessCall_entry(dword_t app, dword_t message, + dword_t arg1, dword_t arg2) { auto result = kernel_state()->app_manager()->DispatchMessageSync(app, message, arg1, arg2); if (result == X_ERROR_NOT_FOUND) { @@ -31,8 +31,9 @@ dword_result_t XMsgInProcessCall(dword_t app, dword_t message, dword_t arg1, } DECLARE_XAM_EXPORT1(XMsgInProcessCall, kNone, kImplemented); -dword_result_t XMsgSystemProcessCall(dword_t app, dword_t message, - dword_t buffer, dword_t buffer_length) { +dword_result_t XMsgSystemProcessCall_entry(dword_t app, dword_t message, + dword_t buffer, + dword_t buffer_length) { auto result = kernel_state()->app_manager()->DispatchMessageAsync( app, message, buffer, buffer_length); if (result == X_ERROR_NOT_FOUND) { @@ -62,13 +63,13 @@ X_HRESULT xeXMsgStartIORequestEx(uint32_t app, uint32_t message, kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, result); result = X_ERROR_IO_PENDING; } - if (result == X_ERROR_SUCCESS || X_ERROR_IO_PENDING) { + if (result == X_ERROR_SUCCESS || result == X_ERROR_IO_PENDING) { XThread::SetLastError(0); } return result; } -dword_result_t XMsgStartIORequestEx( +dword_result_t XMsgStartIORequestEx_entry( dword_t app, dword_t message, pointer_t overlapped_ptr, dword_t buffer_ptr, dword_t buffer_length, pointer_t unknown_ptr) { @@ -77,16 +78,16 @@ dword_result_t XMsgStartIORequestEx( } DECLARE_XAM_EXPORT1(XMsgStartIORequestEx, kNone, kImplemented); -dword_result_t XMsgStartIORequest(dword_t app, dword_t message, - pointer_t overlapped_ptr, - dword_t buffer_ptr, dword_t buffer_length) { +dword_result_t XMsgStartIORequest_entry( + dword_t app, dword_t message, pointer_t overlapped_ptr, + dword_t buffer_ptr, dword_t buffer_length) { return xeXMsgStartIORequestEx(app, message, overlapped_ptr, buffer_ptr, buffer_length, nullptr); } DECLARE_XAM_EXPORT1(XMsgStartIORequest, kNone, kImplemented); -dword_result_t XMsgCancelIORequest(pointer_t overlapped_ptr, - dword_t wait) { +dword_result_t XMsgCancelIORequest_entry( + pointer_t overlapped_ptr, dword_t wait) { X_HANDLE event_handle = XOverlappedGetEvent(overlapped_ptr); if (event_handle && wait) { auto ev = @@ -100,17 +101,18 @@ dword_result_t XMsgCancelIORequest(pointer_t overlapped_ptr, } DECLARE_XAM_EXPORT1(XMsgCancelIORequest, kNone, kImplemented); -dword_result_t XMsgCompleteIORequest(pointer_t overlapped_ptr, - dword_t result, dword_t extended_error, - dword_t length) { +dword_result_t XMsgCompleteIORequest_entry( + pointer_t overlapped_ptr, dword_t result, + dword_t extended_error, dword_t length) { kernel_state()->CompleteOverlappedImmediateEx(overlapped_ptr, result, extended_error, length); return X_ERROR_SUCCESS; } DECLARE_XAM_EXPORT2(XMsgCompleteIORequest, kNone, kImplemented, kSketchy); -dword_result_t XamGetOverlappedResult(pointer_t overlapped_ptr, - lpdword_t length_ptr, dword_t unknown) { +dword_result_t XamGetOverlappedResult_entry( + pointer_t overlapped_ptr, lpdword_t length_ptr, + dword_t unknown) { uint32_t result; if (overlapped_ptr->result != X_ERROR_IO_PENDING) { result = overlapped_ptr->result; @@ -133,9 +135,8 @@ dword_result_t XamGetOverlappedResult(pointer_t overlapped_ptr, } DECLARE_XAM_EXPORT2(XamGetOverlappedResult, kNone, kImplemented, kSketchy); -void RegisterMsgExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Msg); diff --git a/src/xenia/kernel/xam/xam_net.cc b/src/xenia/kernel/xam/xam_net.cc index 4c5c0ead4..a331f139d 100644 --- a/src/xenia/kernel/xam/xam_net.cc +++ b/src/xenia/kernel/xam/xam_net.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -169,8 +169,8 @@ struct XNetStartupParams { XNetStartupParams xnet_startup_params = {0}; -dword_result_t NetDll_XNetStartup(dword_t caller, - pointer_t params) { +dword_result_t NetDll_XNetStartup_entry(dword_t caller, + pointer_t params) { if (params) { assert_true(params->cfgSizeOfStruct == sizeof(XNetStartupParams)); std::memcpy(&xnet_startup_params, params, sizeof(XNetStartupParams)); @@ -191,7 +191,7 @@ dword_result_t NetDll_XNetStartup(dword_t caller, } DECLARE_XAM_EXPORT1(NetDll_XNetStartup, kNetworking, kImplemented); -dword_result_t NetDll_XNetCleanup(dword_t caller, lpvoid_t params) { +dword_result_t NetDll_XNetCleanup_entry(dword_t caller, lpvoid_t params) { auto xam = kernel_state()->GetKernelModule("xam.xex"); // auto xnet = xam->xnet(); // xam->set_xnet(nullptr); @@ -203,8 +203,9 @@ dword_result_t NetDll_XNetCleanup(dword_t caller, lpvoid_t params) { } DECLARE_XAM_EXPORT1(NetDll_XNetCleanup, kNetworking, kImplemented); -dword_result_t NetDll_XNetGetOpt(dword_t one, dword_t option_id, - lpvoid_t buffer_ptr, lpdword_t buffer_size) { +dword_result_t NetDll_XNetGetOpt_entry(dword_t one, dword_t option_id, + lpvoid_t buffer_ptr, + lpdword_t buffer_size) { assert_true(one == 1); switch (option_id) { case 1: @@ -221,8 +222,8 @@ dword_result_t NetDll_XNetGetOpt(dword_t one, dword_t option_id, } DECLARE_XAM_EXPORT1(NetDll_XNetGetOpt, kNetworking, kSketchy); -dword_result_t NetDll_XNetRandom(dword_t caller, lpvoid_t buffer_ptr, - dword_t length) { +dword_result_t NetDll_XNetRandom_entry(dword_t caller, lpvoid_t buffer_ptr, + dword_t length) { // For now, constant values. // This makes replicating things easier. std::memset(buffer_ptr, 0xBB, length); @@ -231,8 +232,8 @@ dword_result_t NetDll_XNetRandom(dword_t caller, lpvoid_t buffer_ptr, } DECLARE_XAM_EXPORT1(NetDll_XNetRandom, kNetworking, kStub); -dword_result_t NetDll_WSAStartup(dword_t caller, word_t version, - pointer_t data_ptr) { +dword_result_t NetDll_WSAStartup_entry(dword_t caller, word_t version, + pointer_t data_ptr) { // TODO(benvanik): abstraction layer needed. #ifdef XE_PLATFORM_WIN32 WSADATA wsaData; @@ -281,22 +282,22 @@ dword_result_t NetDll_WSAStartup(dword_t caller, word_t version, } DECLARE_XAM_EXPORT1(NetDll_WSAStartup, kNetworking, kImplemented); -dword_result_t NetDll_WSACleanup(dword_t caller) { +dword_result_t NetDll_WSACleanup_entry(dword_t caller) { // This does nothing. Xenia needs WSA running. return 0; } DECLARE_XAM_EXPORT1(NetDll_WSACleanup, kNetworking, kImplemented); -dword_result_t NetDll_WSAGetLastError() { return XThread::GetLastError(); } +dword_result_t NetDll_WSAGetLastError_entry() { + return XThread::GetLastError(); +} DECLARE_XAM_EXPORT1(NetDll_WSAGetLastError, kNetworking, kImplemented); -dword_result_t NetDll_WSARecvFrom(dword_t caller, dword_t socket, - pointer_t buffers_ptr, - dword_t buffer_count, - lpdword_t num_bytes_recv, lpdword_t flags_ptr, - pointer_t from_addr, - pointer_t overlapped_ptr, - lpvoid_t completion_routine_ptr) { +dword_result_t NetDll_WSARecvFrom_entry( + dword_t caller, dword_t socket, pointer_t buffers_ptr, + dword_t buffer_count, lpdword_t num_bytes_recv, lpdword_t flags_ptr, + pointer_t from_addr, pointer_t overlapped_ptr, + lpvoid_t completion_routine_ptr) { if (overlapped_ptr) { // auto evt = kernel_state()->object_table()->LookupObject( // overlapped_ptr->event_handle); @@ -314,12 +315,11 @@ DECLARE_XAM_EXPORT2(NetDll_WSARecvFrom, kNetworking, kStub, kHighFrequency); // If the socket is a VDP socket, buffer 0 is the game data length, and buffer 1 // is the unencrypted game data. -dword_result_t NetDll_WSASendTo(dword_t caller, dword_t socket_handle, - pointer_t buffers, dword_t num_buffers, - lpdword_t num_bytes_sent, dword_t flags, - pointer_t to_ptr, dword_t to_len, - pointer_t overlapped, - lpvoid_t completion_routine) { +dword_result_t NetDll_WSASendTo_entry( + dword_t caller, dword_t socket_handle, pointer_t buffers, + dword_t num_buffers, lpdword_t num_bytes_sent, dword_t flags, + pointer_t to_ptr, dword_t to_len, + pointer_t overlapped, lpvoid_t completion_routine) { assert(!overlapped); assert(!completion_routine); @@ -357,11 +357,11 @@ dword_result_t NetDll_WSASendTo(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_WSASendTo, kNetworking, kImplemented); -dword_result_t NetDll_WSAWaitForMultipleEvents(dword_t num_events, - lpdword_t events, - dword_t wait_all, - dword_t timeout, - dword_t alertable) { +dword_result_t NetDll_WSAWaitForMultipleEvents_entry(dword_t num_events, + lpdword_t events, + dword_t wait_all, + dword_t timeout, + dword_t alertable) { if (num_events > 64) { XThread::SetLastError(87); // ERROR_INVALID_PARAMETER return ~0u; @@ -386,14 +386,14 @@ dword_result_t NetDll_WSAWaitForMultipleEvents(dword_t num_events, DECLARE_XAM_EXPORT2(NetDll_WSAWaitForMultipleEvents, kNetworking, kImplemented, kBlocking); -dword_result_t NetDll_WSACreateEvent() { +dword_result_t NetDll_WSACreateEvent_entry() { XEvent* ev = new XEvent(kernel_state()); ev->Initialize(true, false); return ev->handle(); } DECLARE_XAM_EXPORT1(NetDll_WSACreateEvent, kNetworking, kImplemented); -dword_result_t NetDll_WSACloseEvent(dword_t event_handle) { +dword_result_t NetDll_WSACloseEvent_entry(dword_t event_handle) { X_STATUS result = kernel_state()->object_table()->ReleaseHandle(event_handle); if (XFAILED(result)) { uint32_t error = xboxkrnl::xeRtlNtStatusToDosError(result); @@ -404,7 +404,7 @@ dword_result_t NetDll_WSACloseEvent(dword_t event_handle) { } DECLARE_XAM_EXPORT1(NetDll_WSACloseEvent, kNetworking, kImplemented); -dword_result_t NetDll_WSAResetEvent(dword_t event_handle) { +dword_result_t NetDll_WSAResetEvent_entry(dword_t event_handle) { X_STATUS result = xboxkrnl::xeNtClearEvent(event_handle); if (XFAILED(result)) { uint32_t error = xboxkrnl::xeRtlNtStatusToDosError(result); @@ -415,7 +415,7 @@ dword_result_t NetDll_WSAResetEvent(dword_t event_handle) { } DECLARE_XAM_EXPORT1(NetDll_WSAResetEvent, kNetworking, kImplemented); -dword_result_t NetDll_WSASetEvent(dword_t event_handle) { +dword_result_t NetDll_WSASetEvent_entry(dword_t event_handle) { X_STATUS result = xboxkrnl::xeNtSetEvent(event_handle, nullptr); if (XFAILED(result)) { uint32_t error = xboxkrnl::xeRtlNtStatusToDosError(result); @@ -449,8 +449,8 @@ struct XnAddrStatus { static const uint32_t XNET_GET_XNADDR_TROUBLESHOOT = 0x00008000; }; -dword_result_t NetDll_XNetGetTitleXnAddr(dword_t caller, - pointer_t addr_ptr) { +dword_result_t NetDll_XNetGetTitleXnAddr_entry(dword_t caller, + pointer_t addr_ptr) { // Just return a loopback address atm. addr_ptr->ina.s_addr = htonl(INADDR_LOOPBACK); addr_ptr->inaOnline.s_addr = 0; @@ -475,8 +475,8 @@ dword_result_t NetDll_XNetGetTitleXnAddr(dword_t caller, } DECLARE_XAM_EXPORT1(NetDll_XNetGetTitleXnAddr, kNetworking, kStub); -dword_result_t NetDll_XNetGetDebugXnAddr(dword_t caller, - pointer_t addr_ptr) { +dword_result_t NetDll_XNetGetDebugXnAddr_entry(dword_t caller, + pointer_t addr_ptr) { addr_ptr.Zero(); // XNET_GET_XNADDR_NONE causes caller to gracefully return. @@ -484,41 +484,43 @@ dword_result_t NetDll_XNetGetDebugXnAddr(dword_t caller, } DECLARE_XAM_EXPORT1(NetDll_XNetGetDebugXnAddr, kNetworking, kStub); -dword_result_t NetDll_XNetXnAddrToMachineId(dword_t caller, - pointer_t addr_ptr, - lpdword_t id_ptr) { +dword_result_t NetDll_XNetXnAddrToMachineId_entry(dword_t caller, + pointer_t addr_ptr, + lpdword_t id_ptr) { // Tell the caller we're not signed in to live (non-zero ret) return 1; } DECLARE_XAM_EXPORT1(NetDll_XNetXnAddrToMachineId, kNetworking, kStub); -void NetDll_XNetInAddrToString(dword_t caller, dword_t in_addr, - lpstring_t string_out, dword_t string_size) { +void NetDll_XNetInAddrToString_entry(dword_t caller, dword_t in_addr, + lpstring_t string_out, + dword_t string_size) { strncpy(string_out, "666.666.666.666", string_size); } DECLARE_XAM_EXPORT1(NetDll_XNetInAddrToString, kNetworking, kStub); // This converts a XNet address to an IN_ADDR. The IN_ADDR is used for // subsequent socket calls (like a handle to a XNet address) -dword_result_t NetDll_XNetXnAddrToInAddr(dword_t caller, - pointer_t xn_addr, - lpvoid_t xid, lpvoid_t in_addr) { +dword_result_t NetDll_XNetXnAddrToInAddr_entry(dword_t caller, + pointer_t xn_addr, + lpvoid_t xid, lpvoid_t in_addr) { return 1; } DECLARE_XAM_EXPORT1(NetDll_XNetXnAddrToInAddr, kNetworking, kStub); // Does the reverse of the above. // FIXME: Arguments may not be correct. -dword_result_t NetDll_XNetInAddrToXnAddr(dword_t caller, lpvoid_t in_addr, - pointer_t xn_addr, - lpvoid_t xid) { +dword_result_t NetDll_XNetInAddrToXnAddr_entry(dword_t caller, lpvoid_t in_addr, + pointer_t xn_addr, + lpvoid_t xid) { return 1; } DECLARE_XAM_EXPORT1(NetDll_XNetInAddrToXnAddr, kNetworking, kStub); // https://www.google.com/patents/WO2008112448A1?cl=en // Reserves a port for use by system link -dword_result_t NetDll_XNetSetSystemLinkPort(dword_t caller, dword_t port) { +dword_result_t NetDll_XNetSetSystemLinkPort_entry(dword_t caller, + dword_t port) { return 1; } DECLARE_XAM_EXPORT1(NetDll_XNetSetSystemLinkPort, kNetworking, kStub); @@ -532,11 +534,14 @@ struct XEthernetStatus { static const uint32_t XNET_ETHERNET_LINK_HALF_DUPLEX = 0x10; }; -dword_result_t NetDll_XNetGetEthernetLinkStatus(dword_t caller) { return 0; } +dword_result_t NetDll_XNetGetEthernetLinkStatus_entry(dword_t caller) { + return 0; +} DECLARE_XAM_EXPORT1(NetDll_XNetGetEthernetLinkStatus, kNetworking, kStub); -dword_result_t NetDll_XNetDnsLookup(dword_t caller, lpstring_t host, - dword_t event_handle, lpdword_t pdns) { +dword_result_t NetDll_XNetDnsLookup_entry(dword_t caller, lpstring_t host, + dword_t event_handle, + lpdword_t pdns) { // TODO(gibbed): actually implement this if (pdns) { auto dns_guest = kernel_memory()->SystemHeapAlloc(sizeof(XNDNS)); @@ -554,7 +559,8 @@ dword_result_t NetDll_XNetDnsLookup(dword_t caller, lpstring_t host, } DECLARE_XAM_EXPORT1(NetDll_XNetDnsLookup, kNetworking, kStub); -dword_result_t NetDll_XNetDnsRelease(dword_t caller, pointer_t dns) { +dword_result_t NetDll_XNetDnsRelease_entry(dword_t caller, + pointer_t dns) { if (!dns) { return X_STATUS_INVALID_PARAMETER; } @@ -563,9 +569,9 @@ dword_result_t NetDll_XNetDnsRelease(dword_t caller, pointer_t dns) { } DECLARE_XAM_EXPORT1(NetDll_XNetDnsRelease, kNetworking, kStub); -dword_result_t NetDll_XNetQosServiceLookup(dword_t caller, dword_t flags, - dword_t event_handle, - lpdword_t pqos) { +dword_result_t NetDll_XNetQosServiceLookup_entry(dword_t caller, dword_t flags, + dword_t event_handle, + lpdword_t pqos) { // Set pqos as some games will try accessing it despite non-successful result if (pqos) { auto qos_guest = kernel_memory()->SystemHeapAlloc(sizeof(XNQOS)); @@ -583,7 +589,8 @@ dword_result_t NetDll_XNetQosServiceLookup(dword_t caller, dword_t flags, } DECLARE_XAM_EXPORT1(NetDll_XNetQosServiceLookup, kNetworking, kStub); -dword_result_t NetDll_XNetQosRelease(dword_t caller, pointer_t qos) { +dword_result_t NetDll_XNetQosRelease_entry(dword_t caller, + pointer_t qos) { if (!qos) { return X_STATUS_INVALID_PARAMETER; } @@ -592,14 +599,14 @@ dword_result_t NetDll_XNetQosRelease(dword_t caller, pointer_t qos) { } DECLARE_XAM_EXPORT1(NetDll_XNetQosRelease, kNetworking, kStub); -dword_result_t NetDll_XNetQosListen(dword_t caller, lpvoid_t id, lpvoid_t data, - dword_t data_size, dword_t r7, - dword_t flags) { +dword_result_t NetDll_XNetQosListen_entry(dword_t caller, lpvoid_t id, + lpvoid_t data, dword_t data_size, + dword_t r7, dword_t flags) { return X_ERROR_FUNCTION_FAILED; } DECLARE_XAM_EXPORT1(NetDll_XNetQosListen, kNetworking, kStub); -dword_result_t NetDll_inet_addr(lpstring_t addr_ptr) { +dword_result_t NetDll_inet_addr_entry(lpstring_t addr_ptr) { if (!addr_ptr) { return -1; } @@ -616,8 +623,8 @@ dword_result_t NetDll_inet_addr(lpstring_t addr_ptr) { } DECLARE_XAM_EXPORT1(NetDll_inet_addr, kNetworking, kImplemented); -dword_result_t NetDll_socket(dword_t caller, dword_t af, dword_t type, - dword_t protocol) { +dword_result_t NetDll_socket_entry(dword_t caller, dword_t af, dword_t type, + dword_t protocol) { XSocket* socket = new XSocket(kernel_state()); X_STATUS result = socket->Initialize(XSocket::AddressFamily((uint32_t)af), XSocket::Type((uint32_t)type), @@ -635,7 +642,7 @@ dword_result_t NetDll_socket(dword_t caller, dword_t af, dword_t type, } DECLARE_XAM_EXPORT1(NetDll_socket, kNetworking, kImplemented); -dword_result_t NetDll_closesocket(dword_t caller, dword_t socket_handle) { +dword_result_t NetDll_closesocket_entry(dword_t caller, dword_t socket_handle) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -652,7 +659,8 @@ dword_result_t NetDll_closesocket(dword_t caller, dword_t socket_handle) { } DECLARE_XAM_EXPORT1(NetDll_closesocket, kNetworking, kImplemented); -int_result_t NetDll_shutdown(dword_t caller, dword_t socket_handle, int_t how) { +int_result_t NetDll_shutdown_entry(dword_t caller, dword_t socket_handle, + int_t how) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -674,9 +682,9 @@ int_result_t NetDll_shutdown(dword_t caller, dword_t socket_handle, int_t how) { } DECLARE_XAM_EXPORT1(NetDll_shutdown, kNetworking, kImplemented); -dword_result_t NetDll_setsockopt(dword_t caller, dword_t socket_handle, - dword_t level, dword_t optname, - lpvoid_t optval_ptr, dword_t optlen) { +dword_result_t NetDll_setsockopt_entry(dword_t caller, dword_t socket_handle, + dword_t level, dword_t optname, + lpvoid_t optval_ptr, dword_t optlen) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -690,8 +698,8 @@ dword_result_t NetDll_setsockopt(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_setsockopt, kNetworking, kImplemented); -dword_result_t NetDll_ioctlsocket(dword_t caller, dword_t socket_handle, - dword_t cmd, lpvoid_t arg_ptr) { +dword_result_t NetDll_ioctlsocket_entry(dword_t caller, dword_t socket_handle, + dword_t cmd, lpvoid_t arg_ptr) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -711,8 +719,9 @@ dword_result_t NetDll_ioctlsocket(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_ioctlsocket, kNetworking, kImplemented); -dword_result_t NetDll_bind(dword_t caller, dword_t socket_handle, - pointer_t name, dword_t namelen) { +dword_result_t NetDll_bind_entry(dword_t caller, dword_t socket_handle, + pointer_t name, + dword_t namelen) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -732,8 +741,9 @@ dword_result_t NetDll_bind(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_bind, kNetworking, kImplemented); -dword_result_t NetDll_connect(dword_t caller, dword_t socket_handle, - pointer_t name, dword_t namelen) { +dword_result_t NetDll_connect_entry(dword_t caller, dword_t socket_handle, + pointer_t name, + dword_t namelen) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -753,8 +763,8 @@ dword_result_t NetDll_connect(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_connect, kNetworking, kImplemented); -dword_result_t NetDll_listen(dword_t caller, dword_t socket_handle, - int_t backlog) { +dword_result_t NetDll_listen_entry(dword_t caller, dword_t socket_handle, + int_t backlog) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -773,9 +783,9 @@ dword_result_t NetDll_listen(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_listen, kNetworking, kImplemented); -dword_result_t NetDll_accept(dword_t caller, dword_t socket_handle, - pointer_t addr_ptr, - lpdword_t addrlen_ptr) { +dword_result_t NetDll_accept_entry(dword_t caller, dword_t socket_handle, + pointer_t addr_ptr, + lpdword_t addrlen_ptr) { if (!addr_ptr) { // WSAEFAULT XThread::SetLastError(0x271E); @@ -858,11 +868,11 @@ struct host_set { } }; -int_result_t NetDll_select(int_t caller, int_t nfds, - pointer_t readfds, - pointer_t writefds, - pointer_t exceptfds, - lpvoid_t timeout_ptr) { +int_result_t NetDll_select_entry(int_t caller, int_t nfds, + pointer_t readfds, + pointer_t writefds, + pointer_t exceptfds, + lpvoid_t timeout_ptr) { host_set host_readfds = {0}; fd_set native_readfds = {0}; if (readfds) { @@ -912,8 +922,9 @@ int_result_t NetDll_select(int_t caller, int_t nfds, } DECLARE_XAM_EXPORT1(NetDll_select, kNetworking, kImplemented); -dword_result_t NetDll_recv(dword_t caller, dword_t socket_handle, - lpvoid_t buf_ptr, dword_t buf_len, dword_t flags) { +dword_result_t NetDll_recv_entry(dword_t caller, dword_t socket_handle, + lpvoid_t buf_ptr, dword_t buf_len, + dword_t flags) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -926,10 +937,11 @@ dword_result_t NetDll_recv(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_recv, kNetworking, kImplemented); -dword_result_t NetDll_recvfrom(dword_t caller, dword_t socket_handle, - lpvoid_t buf_ptr, dword_t buf_len, dword_t flags, - pointer_t from_ptr, - lpdword_t fromlen_ptr) { +dword_result_t NetDll_recvfrom_entry(dword_t caller, dword_t socket_handle, + lpvoid_t buf_ptr, dword_t buf_len, + dword_t flags, + pointer_t from_ptr, + lpdword_t fromlen_ptr) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -970,8 +982,9 @@ dword_result_t NetDll_recvfrom(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_recvfrom, kNetworking, kImplemented); -dword_result_t NetDll_send(dword_t caller, dword_t socket_handle, - lpvoid_t buf_ptr, dword_t buf_len, dword_t flags) { +dword_result_t NetDll_send_entry(dword_t caller, dword_t socket_handle, + lpvoid_t buf_ptr, dword_t buf_len, + dword_t flags) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -984,9 +997,11 @@ dword_result_t NetDll_send(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_send, kNetworking, kImplemented); -dword_result_t NetDll_sendto(dword_t caller, dword_t socket_handle, - lpvoid_t buf_ptr, dword_t buf_len, dword_t flags, - pointer_t to_ptr, dword_t to_len) { +dword_result_t NetDll_sendto_entry(dword_t caller, dword_t socket_handle, + lpvoid_t buf_ptr, dword_t buf_len, + dword_t flags, + pointer_t to_ptr, + dword_t to_len) { auto socket = kernel_state()->object_table()->LookupObject(socket_handle); if (!socket) { @@ -1000,8 +1015,8 @@ dword_result_t NetDll_sendto(dword_t caller, dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll_sendto, kNetworking, kImplemented); -dword_result_t NetDll___WSAFDIsSet(dword_t socket_handle, - pointer_t fd_set) { +dword_result_t NetDll___WSAFDIsSet_entry(dword_t socket_handle, + pointer_t fd_set) { for (uint32_t i = 0; i < fd_set->fd_count.value; i++) { if (fd_set->fd_array[i] == socket_handle) { return 1; @@ -1011,14 +1026,13 @@ dword_result_t NetDll___WSAFDIsSet(dword_t socket_handle, } DECLARE_XAM_EXPORT1(NetDll___WSAFDIsSet, kNetworking, kImplemented); -void NetDll_WSASetLastError(dword_t error_code) { +void NetDll_WSASetLastError_entry(dword_t error_code) { XThread::SetLastError(error_code); } DECLARE_XAM_EXPORT1(NetDll_WSASetLastError, kNetworking, kImplemented); -void RegisterNetExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Net); diff --git a/src/xenia/kernel/xam/xam_notify.cc b/src/xenia/kernel/xam/xam_notify.cc index 6d09df7f3..71bc59807 100644 --- a/src/xenia/kernel/xam/xam_notify.cc +++ b/src/xenia/kernel/xam/xam_notify.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -36,20 +36,22 @@ uint32_t xeXamNotifyCreateListener(uint64_t mask, uint32_t is_system, return handle; } -dword_result_t XamNotifyCreateListener(qword_t mask, dword_t max_version) { +dword_result_t XamNotifyCreateListener_entry(qword_t mask, + dword_t max_version) { return xeXamNotifyCreateListener(mask, 0, max_version); } DECLARE_XAM_EXPORT1(XamNotifyCreateListener, kNone, kImplemented); -dword_result_t XamNotifyCreateListenerInternal(qword_t mask, dword_t is_system, - dword_t max_version) { +dword_result_t XamNotifyCreateListenerInternal_entry(qword_t mask, + dword_t is_system, + dword_t max_version) { return xeXamNotifyCreateListener(mask, is_system, max_version); } DECLARE_XAM_EXPORT1(XamNotifyCreateListenerInternal, kNone, kImplemented); // https://github.com/CodeAsm/ffplay360/blob/master/Common/AtgSignIn.cpp -dword_result_t XNotifyGetNext(dword_t handle, dword_t match_id, - lpdword_t id_ptr, lpdword_t param_ptr) { +dword_result_t XNotifyGetNext_entry(dword_t handle, dword_t match_id, + lpdword_t id_ptr, lpdword_t param_ptr) { if (param_ptr) { *param_ptr = 0; } @@ -89,20 +91,19 @@ dword_result_t XNotifyGetNext(dword_t handle, dword_t match_id, } DECLARE_XAM_EXPORT2(XNotifyGetNext, kNone, kImplemented, kHighFrequency); -dword_result_t XNotifyDelayUI(dword_t delay_ms) { +dword_result_t XNotifyDelayUI_entry(dword_t delay_ms) { // Ignored. return 0; } DECLARE_XAM_EXPORT1(XNotifyDelayUI, kNone, kStub); -void XNotifyPositionUI(dword_t position) { +void XNotifyPositionUI_entry(dword_t position) { // Ignored. } DECLARE_XAM_EXPORT1(XNotifyPositionUI, kNone, kStub); -void RegisterNotifyExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel -} // namespace xe \ No newline at end of file +} // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Notify); diff --git a/src/xenia/kernel/xam/xam_nui.cc b/src/xenia/kernel/xam/xam_nui.cc index d0f99087d..53fe06e6f 100644 --- a/src/xenia/kernel/xam/xam_nui.cc +++ b/src/xenia/kernel/xam/xam_nui.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -14,6 +14,7 @@ #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xam/xam_private.h" #include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" @@ -34,14 +35,14 @@ struct X_NUI_DEVICE_STATUS { }; static_assert(sizeof(X_NUI_DEVICE_STATUS) == 24, "Size matters"); -void XamNuiGetDeviceStatus(pointer_t status_ptr) { +void XamNuiGetDeviceStatus_entry(pointer_t status_ptr) { status_ptr.Zero(); status_ptr->status = 0; // Not connected. } DECLARE_XAM_EXPORT1(XamNuiGetDeviceStatus, kNone, kStub); -dword_result_t XamShowNuiTroubleshooterUI(unknown_t unk1, unknown_t unk2, - unknown_t unk3) { +dword_result_t XamShowNuiTroubleshooterUI_entry(unknown_t unk1, unknown_t unk2, + unknown_t unk3) { // unk1 is 0xFF - possibly user index? // unk2, unk3 appear to always be zero. @@ -49,26 +50,29 @@ dword_result_t XamShowNuiTroubleshooterUI(unknown_t unk1, unknown_t unk2, return 0; } - auto display_window = kernel_state()->emulator()->display_window(); - xe::threading::Fence fence; - if (display_window->app_context().CallInUIThreadSynchronous([&]() { - xe::ui::ImGuiDialog::ShowMessageBox( - display_window, "NUI Troubleshooter", - "The game has indicated there is a problem with NUI (Kinect).") - ->Then(&fence); - })) { - ++xam_dialogs_shown_; - fence.Wait(); - --xam_dialogs_shown_; + const Emulator* emulator = kernel_state()->emulator(); + ui::Window* display_window = emulator->display_window(); + ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer(); + if (display_window && imgui_drawer) { + xe::threading::Fence fence; + if (display_window->app_context().CallInUIThreadSynchronous([&]() { + xe::ui::ImGuiDialog::ShowMessageBox( + imgui_drawer, "NUI Troubleshooter", + "The game has indicated there is a problem with NUI (Kinect).") + ->Then(&fence); + })) { + ++xam_dialogs_shown_; + fence.Wait(); + --xam_dialogs_shown_; + } } return 0; } DECLARE_XAM_EXPORT1(XamShowNuiTroubleshooterUI, kNone, kStub); -void RegisterNUIExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(NUI); diff --git a/src/xenia/kernel/xam/xam_party.cc b/src/xenia/kernel/xam/xam_party.cc index 5476f0b33..d278be996 100644 --- a/src/xenia/kernel/xam/xam_party.cc +++ b/src/xenia/kernel/xam/xam_party.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -16,30 +16,32 @@ namespace xe { namespace kernel { namespace xam { -dword_result_t XamPartyGetUserList(dword_t player_count, lpdword_t party_list) { +dword_result_t XamPartyGetUserList_entry(dword_t player_count, + lpdword_t party_list) { // 5345085D wants specifically this code to skip loading party data. // This code is not documented in NT_STATUS code list return 0x807D0003; } DECLARE_XAM_EXPORT1(XamPartyGetUserList, kNone, kStub); -dword_result_t XamPartySendGameInvites(dword_t r3, dword_t r4, dword_t r5) { +dword_result_t XamPartySendGameInvites_entry(dword_t r3, dword_t r4, + dword_t r5) { return X_ERROR_FUNCTION_FAILED; } DECLARE_XAM_EXPORT1(XamPartySendGameInvites, kNone, kStub); -dword_result_t XamPartySetCustomData(dword_t r3, dword_t r4, dword_t r5) { +dword_result_t XamPartySetCustomData_entry(dword_t r3, dword_t r4, dword_t r5) { return X_ERROR_FUNCTION_FAILED; } DECLARE_XAM_EXPORT1(XamPartySetCustomData, kNone, kStub); -dword_result_t XamPartyGetBandwidth(dword_t r3, dword_t r4) { +dword_result_t XamPartyGetBandwidth_entry(dword_t r3, dword_t r4) { return X_ERROR_FUNCTION_FAILED; } DECLARE_XAM_EXPORT1(XamPartyGetBandwidth, kNone, kStub); -void RegisterPartyExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Party); diff --git a/src/xenia/kernel/xam/xam_task.cc b/src/xenia/kernel/xam/xam_task.cc index 58f314079..7fe6eb4d3 100644 --- a/src/xenia/kernel/xam/xam_task.cc +++ b/src/xenia/kernel/xam/xam_task.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -39,9 +39,9 @@ struct XTASK_MESSAGE { }; static_assert_size(XTASK_MESSAGE, 0x1C); -dword_result_t XamTaskSchedule(lpvoid_t callback, - pointer_t message, - lpdword_t unknown, lpdword_t handle_ptr) { +dword_result_t XamTaskSchedule_entry(lpvoid_t callback, + pointer_t message, + lpdword_t unknown, lpdword_t handle_ptr) { // TODO(gibbed): figure out what this is for *handle_ptr = 12345; @@ -69,12 +69,11 @@ dword_result_t XamTaskSchedule(lpvoid_t callback, } DECLARE_XAM_EXPORT2(XamTaskSchedule, kNone, kImplemented, kSketchy); -dword_result_t XamTaskShouldExit(dword_t r3) { return 0; } +dword_result_t XamTaskShouldExit_entry(dword_t r3) { return 0; } DECLARE_XAM_EXPORT2(XamTaskShouldExit, kNone, kStub, kSketchy); -void RegisterTaskExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Task); diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index 21b0590d6..be8e2c892 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -16,6 +16,7 @@ #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xam/xam_private.h" #include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" @@ -51,7 +52,8 @@ class XamDialog : public xe::ui::ImGuiDialog { } protected: - XamDialog(xe::ui::Window* window) : xe::ui::ImGuiDialog(window) {} + XamDialog(xe::ui::ImGuiDrawer* imgui_drawer) + : xe::ui::ImGuiDialog(imgui_drawer) {} void OnClose() override { if (close_callback_) { @@ -201,15 +203,15 @@ X_RESULT xeXamDispatchHeadlessEx( } } -dword_result_t XamIsUIActive() { return xeXamIsUIActive(); } +dword_result_t XamIsUIActive_entry() { return xeXamIsUIActive(); } DECLARE_XAM_EXPORT2(XamIsUIActive, kUI, kImplemented, kHighFrequency); class MessageBoxDialog : public XamDialog { public: - MessageBoxDialog(xe::ui::Window* window, std::string title, + MessageBoxDialog(xe::ui::ImGuiDrawer* imgui_drawer, std::string title, std::string description, std::vector buttons, uint32_t default_button) - : XamDialog(window), + : XamDialog(imgui_drawer), title_(title), description_(description), buttons_(std::move(buttons)), @@ -263,11 +265,10 @@ class MessageBoxDialog : public XamDialog { }; // https://www.se7ensins.com/forums/threads/working-xshowmessageboxui.844116/ -dword_result_t XamShowMessageBoxUI(dword_t user_index, lpu16string_t title_ptr, - lpu16string_t text_ptr, dword_t button_count, - lpdword_t button_ptrs, dword_t active_button, - dword_t flags, lpdword_t result_ptr, - pointer_t overlapped) { +dword_result_t XamShowMessageBoxUI_entry( + dword_t user_index, lpu16string_t title_ptr, lpu16string_t text_ptr, + dword_t button_count, lpdword_t button_ptrs, dword_t active_button, + dword_t flags, lpdword_t result_ptr, pointer_t overlapped) { std::string title; if (title_ptr) { title = xe::to_utf8(title_ptr.value()); @@ -311,11 +312,11 @@ dword_result_t XamShowMessageBoxUI(dword_t user_index, lpu16string_t title_ptr, *result_ptr = dialog->chosen_button(); return X_ERROR_SUCCESS; }; - auto display_window = kernel_state()->emulator()->display_window(); + const Emulator* emulator = kernel_state()->emulator(); + ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer(); result = xeXamDispatchDialog( - new MessageBoxDialog(display_window, title, - xe::to_utf8(text_ptr.value()), buttons, - active_button), + new MessageBoxDialog(imgui_drawer, title, xe::to_utf8(text_ptr.value()), + buttons, active_button), close, overlapped); } return result; @@ -324,10 +325,10 @@ DECLARE_XAM_EXPORT1(XamShowMessageBoxUI, kUI, kImplemented); class KeyboardInputDialog : public XamDialog { public: - KeyboardInputDialog(xe::ui::Window* window, std::string title, + KeyboardInputDialog(xe::ui::ImGuiDrawer* imgui_drawer, std::string title, std::string description, std::string default_text, size_t max_length) - : XamDialog(window), + : XamDialog(imgui_drawer), title_(title), description_(description), default_text_(default_text), @@ -404,11 +405,10 @@ class KeyboardInputDialog : public XamDialog { }; // https://www.se7ensins.com/forums/threads/release-how-to-use-xshowkeyboardui-release.906568/ -dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags, - lpu16string_t default_text, - lpu16string_t title, lpu16string_t description, - lpu16string_t buffer, dword_t buffer_length, - pointer_t overlapped) { +dword_result_t XamShowKeyboardUI_entry( + dword_t user_index, dword_t flags, lpu16string_t default_text, + lpu16string_t title, lpu16string_t description, lpu16string_t buffer, + dword_t buffer_length, pointer_t overlapped) { if (!buffer) { return X_ERROR_INVALID_PARAMETER; } @@ -448,10 +448,11 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags, return X_ERROR_SUCCESS; } }; - auto display_window = kernel_state()->emulator()->display_window(); + const Emulator* emulator = kernel_state()->emulator(); + ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer(); result = xeXamDispatchDialogEx( new KeyboardInputDialog( - display_window, title ? xe::to_utf8(title.value()) : "", + imgui_drawer, title ? xe::to_utf8(title.value()) : "", description ? xe::to_utf8(description.value()) : "", default_text ? xe::to_utf8(default_text.value()) : "", buffer_length), @@ -461,11 +462,10 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags, } DECLARE_XAM_EXPORT1(XamShowKeyboardUI, kUI, kImplemented); -dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type, - dword_t content_flags, - qword_t total_requested, - lpdword_t device_id_ptr, - pointer_t overlapped) { +dword_result_t XamShowDeviceSelectorUI_entry( + dword_t user_index, dword_t content_type, dword_t content_flags, + qword_t total_requested, lpdword_t device_id_ptr, + pointer_t overlapped) { return xeXamDispatchHeadless( [device_id_ptr]() -> X_RESULT { // NOTE: 0x00000001 is our dummy device ID from xam_content.cc @@ -476,16 +476,17 @@ dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type, } DECLARE_XAM_EXPORT1(XamShowDeviceSelectorUI, kUI, kImplemented); -void XamShowDirtyDiscErrorUI(dword_t user_index) { +void XamShowDirtyDiscErrorUI_entry(dword_t user_index) { if (cvars::headless) { assert_always(); exit(1); return; } - auto display_window = kernel_state()->emulator()->display_window(); + const Emulator* emulator = kernel_state()->emulator(); + ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer(); xeXamDispatchDialog( new MessageBoxDialog( - display_window, "Disc Read Error", + imgui_drawer, "Disc Read Error", "There's been an issue reading content from the game disc.\nThis is " "likely caused by bad or unimplemented file IO calls.", {"OK"}, 0), @@ -496,19 +497,18 @@ void XamShowDirtyDiscErrorUI(dword_t user_index) { } DECLARE_XAM_EXPORT1(XamShowDirtyDiscErrorUI, kUI, kImplemented); -dword_result_t XamShowPartyUI(unknown_t r3, unknown_t r4) { +dword_result_t XamShowPartyUI_entry(unknown_t r3, unknown_t r4) { return X_ERROR_FUNCTION_FAILED; } DECLARE_XAM_EXPORT1(XamShowPartyUI, kNone, kStub); -dword_result_t XamShowCommunitySessionsUI(unknown_t r3, unknown_t r4) { +dword_result_t XamShowCommunitySessionsUI_entry(unknown_t r3, unknown_t r4) { return X_ERROR_FUNCTION_FAILED; } DECLARE_XAM_EXPORT1(XamShowCommunitySessionsUI, kNone, kStub); -void RegisterUIExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(UI); diff --git a/src/xenia/kernel/xam/xam_user.cc b/src/xenia/kernel/xam/xam_user.cc index 612cc326c..2155504e8 100644 --- a/src/xenia/kernel/xam/xam_user.cc +++ b/src/xenia/kernel/xam/xam_user.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -14,6 +14,7 @@ #include "xenia/base/string_util.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" +#include "xenia/kernel/xam/user_profile.h" #include "xenia/kernel/xam/xam_private.h" #include "xenia/kernel/xenumerator.h" #include "xenia/kernel/xthread.h" @@ -23,8 +24,8 @@ namespace xe { namespace kernel { namespace xam { -X_HRESULT_result_t XamUserGetXUID(dword_t user_index, dword_t type_mask, - lpqword_t xuid_ptr) { +X_HRESULT_result_t XamUserGetXUID_entry(dword_t user_index, dword_t type_mask, + lpqword_t xuid_ptr) { assert_true(type_mask == 1 || type_mask == 2 || type_mask == 3 || type_mask == 4 || type_mask == 7); if (!xuid_ptr) { @@ -54,7 +55,7 @@ X_HRESULT_result_t XamUserGetXUID(dword_t user_index, dword_t type_mask, } DECLARE_XAM_EXPORT1(XamUserGetXUID, kUserProfiles, kImplemented); -dword_result_t XamUserGetSigninState(dword_t user_index) { +dword_result_t XamUserGetSigninState_entry(dword_t user_index) { // Yield, as some games spam this. xe::threading::MaybeYield(); uint32_t signin_state = 0; @@ -79,8 +80,8 @@ typedef struct { } X_USER_SIGNIN_INFO; static_assert_size(X_USER_SIGNIN_INFO, 40); -X_HRESULT_result_t XamUserGetSigninInfo(dword_t user_index, dword_t flags, - pointer_t info) { +X_HRESULT_result_t XamUserGetSigninInfo_entry( + dword_t user_index, dword_t flags, pointer_t info) { if (!info) { return X_E_INVALIDARG; } @@ -99,8 +100,8 @@ X_HRESULT_result_t XamUserGetSigninInfo(dword_t user_index, dword_t flags, } DECLARE_XAM_EXPORT1(XamUserGetSigninInfo, kUserProfiles, kImplemented); -dword_result_t XamUserGetName(dword_t user_index, lpstring_t buffer, - dword_t buffer_len) { +dword_result_t XamUserGetName_entry(dword_t user_index, lpstring_t buffer, + dword_t buffer_len) { if (user_index >= 4) { return X_E_INVALIDARG; } @@ -117,8 +118,9 @@ dword_result_t XamUserGetName(dword_t user_index, lpstring_t buffer, } DECLARE_XAM_EXPORT1(XamUserGetName, kUserProfiles, kImplemented); -dword_result_t XamUserGetGamerTag(dword_t user_index, lpu16string_t buffer, - dword_t buffer_len) { +dword_result_t XamUserGetGamerTag_entry(dword_t user_index, + lpu16string_t buffer, + dword_t buffer_len) { if (user_index >= 4) { return X_E_INVALIDARG; } @@ -145,25 +147,14 @@ typedef struct { } X_USER_READ_PROFILE_SETTINGS; static_assert_size(X_USER_READ_PROFILE_SETTINGS, 8); -typedef struct { - xe::be from; - xe::be unk04; - xe::be user_index; - xe::be unk0C; - xe::be setting_id; - xe::be unk14; - uint8_t setting_data[16]; -} X_USER_READ_PROFILE_SETTING; -static_assert_size(X_USER_READ_PROFILE_SETTING, 40); - // https://github.com/oukiar/freestyledash/blob/master/Freestyle/Tools/Generic/xboxtools.cpp -uint32_t xeXamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index, - uint32_t xuid_count, lpqword_t xuids, - uint32_t setting_count, - lpdword_t setting_ids, uint32_t unk, - lpdword_t buffer_size_ptr, - lpvoid_t buffer_ptr, - uint32_t overlapped_ptr) { +uint32_t XamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index, + uint32_t xuid_count, be* xuids, + uint32_t setting_count, + be* setting_ids, uint32_t unk, + be* buffer_size_ptr, + uint8_t* buffer, + XAM_OVERLAPPED* overlapped) { if (!xuid_count) { assert_null(xuids); } else { @@ -172,8 +163,11 @@ uint32_t xeXamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index, // TODO(gibbed): allow proper lookup of arbitrary XUIDs const auto& user_profile = kernel_state()->user_profile(); assert_true(static_cast(xuids[0]) == user_profile->xuid()); + // TODO(gibbed): we assert here, but in case a title passes xuid_count > 1 + // until it's implemented for release builds... + xuid_count = 1; } - assert_zero(unk); + assert_zero(unk); // probably flags // must have at least 1 to 32 settings if (setting_count < 1 || setting_count > 32) { @@ -187,35 +181,33 @@ uint32_t xeXamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index, // if buffer size is non-zero, buffer pointer must be valid auto buffer_size = static_cast(*buffer_size_ptr); - if (buffer_size && !buffer_ptr) { + if (buffer_size && !buffer) { return X_ERROR_INVALID_PARAMETER; } uint32_t needed_header_size = 0; - uint32_t needed_extra_size = 0; + uint32_t needed_data_size = 0; for (uint32_t i = 0; i < setting_count; ++i) { - needed_header_size += sizeof(X_USER_READ_PROFILE_SETTING); + needed_header_size += sizeof(X_USER_PROFILE_SETTING); UserProfile::Setting::Key setting_key; setting_key.value = static_cast(setting_ids[i]); switch (static_cast(setting_key.type)) { case UserProfile::Setting::Type::WSTRING: - case UserProfile::Setting::Type::BINARY: { - needed_extra_size += setting_key.size; + case UserProfile::Setting::Type::BINARY: + needed_data_size += setting_key.size; break; - } - default: { + default: break; - } } } if (xuids) { - // needed_header_size *= xuid_count; - // needed_extra_size *= !xuid_count; + needed_header_size *= xuid_count; + needed_data_size *= xuid_count; } needed_header_size += sizeof(X_USER_READ_PROFILE_SETTINGS); - uint32_t needed_size = needed_header_size + needed_extra_size; - if (!buffer_ptr || buffer_size < needed_size) { + uint32_t needed_size = needed_header_size + needed_data_size; + if (!buffer || buffer_size < needed_size) { if (!buffer_size) { *buffer_size_ptr = needed_size; } @@ -225,11 +217,12 @@ uint32_t xeXamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index, // Title ID = 0 means us. // 0xfffe07d1 = profile? - if (user_index) { + if (!xuids && user_index) { // Only support user 0. - if (overlapped_ptr) { - kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, - X_ERROR_NO_SUCH_USER); + if (overlapped) { + kernel_state()->CompleteOverlappedImmediate( + kernel_state()->memory()->HostToGuestVirtual(overlapped), + X_ERROR_NO_SUCH_USER); return X_ERROR_IO_PENDING; } return X_ERROR_NO_SUCH_USER; @@ -256,108 +249,86 @@ uint32_t xeXamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index, } if (any_missing) { // TODO(benvanik): don't fail? most games don't even check! - if (overlapped_ptr) { - kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, - X_ERROR_INVALID_PARAMETER); + if (overlapped) { + kernel_state()->CompleteOverlappedImmediate( + kernel_state()->memory()->HostToGuestVirtual(overlapped), + X_ERROR_INVALID_PARAMETER); return X_ERROR_IO_PENDING; } return X_ERROR_INVALID_PARAMETER; } - auto out_header = buffer_ptr.as(); + auto out_header = reinterpret_cast(buffer); + auto out_setting = reinterpret_cast(&out_header[1]); out_header->setting_count = static_cast(setting_count); - out_header->settings_ptr = buffer_ptr.guest_address() + 8; + out_header->settings_ptr = + kernel_state()->memory()->HostToGuestVirtual(out_setting); - auto out_setting = - reinterpret_cast(&out_header[1]); - - size_t buffer_offset = needed_header_size; + UserProfile::SettingByteStream out_stream( + kernel_state()->memory()->HostToGuestVirtual(buffer), buffer, buffer_size, + needed_header_size); for (uint32_t n = 0; n < setting_count; ++n) { uint32_t setting_id = setting_ids[n]; auto setting = user_profile->GetSetting(setting_id); - std::memset(out_setting, 0, sizeof(X_USER_READ_PROFILE_SETTING)); + std::memset(out_setting, 0, sizeof(X_USER_PROFILE_SETTING)); out_setting->from = !setting || !setting->is_set ? 0 : setting->is_title_specific() ? 2 : 1; - out_setting->user_index = static_cast(user_index); + if (xuids) { + out_setting->xuid = user_profile->xuid(); + } else { + out_setting->user_index = static_cast(user_index); + } out_setting->setting_id = setting_id; if (setting && setting->is_set) { - buffer_offset = - setting->Append(&out_setting->setting_data[0], buffer_ptr, - buffer_ptr.guest_address(), buffer_offset); + setting->Append(&out_setting->data, &out_stream); } - // TODO(benvanik): why did I do this? - /*else { - std::memset(&out_setting->setting_data[0], 0, - sizeof(out_setting->setting_data)); - }*/ ++out_setting; } - if (overlapped_ptr) { - kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, - X_ERROR_SUCCESS); + if (overlapped) { + kernel_state()->CompleteOverlappedImmediate( + kernel_state()->memory()->HostToGuestVirtual(overlapped), + X_ERROR_SUCCESS); return X_ERROR_IO_PENDING; } return X_ERROR_SUCCESS; } -dword_result_t XamUserReadProfileSettings( +dword_result_t XamUserReadProfileSettings_entry( dword_t title_id, dword_t user_index, dword_t xuid_count, lpqword_t xuids, dword_t setting_count, lpdword_t setting_ids, lpdword_t buffer_size_ptr, - lpvoid_t buffer_ptr, dword_t overlapped_ptr) { - return xeXamUserReadProfileSettingsEx( - title_id, user_index, xuid_count, xuids, setting_count, setting_ids, 0, - buffer_size_ptr, buffer_ptr, overlapped_ptr); + lpvoid_t buffer_ptr, pointer_t overlapped) { + return XamUserReadProfileSettingsEx(title_id, user_index, xuid_count, xuids, + setting_count, setting_ids, 0, + buffer_size_ptr, buffer_ptr, overlapped); } DECLARE_XAM_EXPORT1(XamUserReadProfileSettings, kUserProfiles, kImplemented); -dword_result_t XamUserReadProfileSettingsEx( +dword_result_t XamUserReadProfileSettingsEx_entry( dword_t title_id, dword_t user_index, dword_t xuid_count, lpqword_t xuids, dword_t setting_count, lpdword_t setting_ids, lpdword_t buffer_size_ptr, - dword_t unk_2, lpvoid_t buffer_ptr, dword_t overlapped_ptr) { - return xeXamUserReadProfileSettingsEx( - title_id, user_index, xuid_count, xuids, setting_count, setting_ids, - unk_2, buffer_size_ptr, buffer_ptr, overlapped_ptr); + dword_t unk_2, lpvoid_t buffer_ptr, pointer_t overlapped) { + return XamUserReadProfileSettingsEx(title_id, user_index, xuid_count, xuids, + setting_count, setting_ids, unk_2, + buffer_size_ptr, buffer_ptr, overlapped); } DECLARE_XAM_EXPORT1(XamUserReadProfileSettingsEx, kUserProfiles, kImplemented); -typedef struct { - xe::be from; - xe::be unk_04; - xe::be unk_08; - xe::be unk_0c; - xe::be setting_id; - xe::be unk_14; - - // UserProfile::Setting::Type. Appears to be 8-in-32 field, and the upper 24 - // are not always zeroed by the game. - uint8_t type; - - xe::be unk_1c; - // TODO(sabretooth): not sure if this is a union, but it seems likely. - // Haven't run into cases other than "binary data" yet. - union { - struct { - xe::be length; - xe::be ptr; - } binary; - }; -} X_USER_WRITE_PROFILE_SETTING; - -dword_result_t XamUserWriteProfileSettings( +dword_result_t XamUserWriteProfileSettings_entry( dword_t title_id, dword_t user_index, dword_t setting_count, - pointer_t settings, dword_t overlapped_ptr) { + pointer_t settings, + pointer_t overlapped) { if (!setting_count || !settings) { return X_ERROR_INVALID_PARAMETER; } if (user_index) { // Only support user 0. - if (overlapped_ptr) { - kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, + if (overlapped) { + kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_NO_SUCH_USER); return X_ERROR_IO_PENDING; } @@ -368,39 +339,39 @@ dword_result_t XamUserWriteProfileSettings( const auto& user_profile = kernel_state()->user_profile(); for (uint32_t n = 0; n < setting_count; ++n) { - const X_USER_WRITE_PROFILE_SETTING& settings_data = settings[n]; + const X_USER_PROFILE_SETTING& setting = settings[n]; + + auto setting_type = + static_cast(setting.data.type); + if (setting_type == UserProfile::Setting::Type::UNSET) { + continue; + } + XELOGD( "XamUserWriteProfileSettings: setting index [{}]:" " from={} setting_id={:08X} data.type={}", - n, (uint32_t)settings_data.from, (uint32_t)settings_data.setting_id, - settings_data.type); + n, (uint32_t)setting.from, (uint32_t)setting.setting_id, + setting.data.type); - xam::UserProfile::Setting::Type settingType = - static_cast(settings_data.type); - - switch (settingType) { + switch (setting_type) { case UserProfile::Setting::Type::CONTENT: case UserProfile::Setting::Type::BINARY: { - uint8_t* settings_data_ptr = kernel_state()->memory()->TranslateVirtual( - settings_data.binary.ptr); - size_t settings_data_len = settings_data.binary.length; - std::vector data_vec; - - if (settings_data.binary.ptr) { + uint8_t* binary_ptr = + kernel_state()->memory()->TranslateVirtual(setting.data.binary.ptr); + size_t binary_size = setting.data.binary.size; + std::vector bytes; + if (setting.data.binary.ptr) { // Copy provided data - data_vec.resize(settings_data_len); - std::memcpy(data_vec.data(), settings_data_ptr, settings_data_len); + bytes.resize(binary_size); + std::memcpy(bytes.data(), binary_ptr, binary_size); } else { // Data pointer was NULL, so just fill with zeroes - data_vec.resize(settings_data_len, 0); + bytes.resize(binary_size, 0); } - user_profile->AddSetting( std::make_unique( - settings_data.setting_id, data_vec)); - + setting.setting_id, bytes)); } break; - case UserProfile::Setting::Type::WSTRING: case UserProfile::Setting::Type::DOUBLE: case UserProfile::Setting::Type::FLOAT: @@ -409,22 +380,21 @@ dword_result_t XamUserWriteProfileSettings( case UserProfile::Setting::Type::DATETIME: default: { XELOGE("XamUserWriteProfileSettings: Unimplemented data type {}", - settingType); + setting_type); } break; }; } - if (overlapped_ptr) { - kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, - X_ERROR_SUCCESS); + if (overlapped) { + kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS); return X_ERROR_IO_PENDING; } return X_ERROR_SUCCESS; } DECLARE_XAM_EXPORT1(XamUserWriteProfileSettings, kUserProfiles, kImplemented); -dword_result_t XamUserCheckPrivilege(dword_t user_index, dword_t mask, - lpdword_t out_value) { +dword_result_t XamUserCheckPrivilege_entry(dword_t user_index, dword_t mask, + lpdword_t out_value) { // checking all users? if (user_index != 0xFF) { if (user_index >= 4) { @@ -442,8 +412,8 @@ dword_result_t XamUserCheckPrivilege(dword_t user_index, dword_t mask, } DECLARE_XAM_EXPORT1(XamUserCheckPrivilege, kUserProfiles, kStub); -dword_result_t XamUserContentRestrictionGetFlags(dword_t user_index, - lpdword_t out_flags) { +dword_result_t XamUserContentRestrictionGetFlags_entry(dword_t user_index, + lpdword_t out_flags) { if (user_index) { return X_ERROR_NO_SUCH_USER; } @@ -454,10 +424,10 @@ dword_result_t XamUserContentRestrictionGetFlags(dword_t user_index, } DECLARE_XAM_EXPORT1(XamUserContentRestrictionGetFlags, kUserProfiles, kStub); -dword_result_t XamUserContentRestrictionGetRating(dword_t user_index, - dword_t unk1, - lpdword_t out_unk2, - lpdword_t out_unk3) { +dword_result_t XamUserContentRestrictionGetRating_entry(dword_t user_index, + dword_t unk1, + lpdword_t out_unk2, + lpdword_t out_unk3) { if (user_index) { return X_ERROR_NO_SUCH_USER; } @@ -470,11 +440,9 @@ dword_result_t XamUserContentRestrictionGetRating(dword_t user_index, } DECLARE_XAM_EXPORT1(XamUserContentRestrictionGetRating, kUserProfiles, kStub); -dword_result_t XamUserContentRestrictionCheckAccess(dword_t user_index, - dword_t unk1, dword_t unk2, - dword_t unk3, dword_t unk4, - lpdword_t out_unk5, - dword_t overlapped_ptr) { +dword_result_t XamUserContentRestrictionCheckAccess_entry( + dword_t user_index, dword_t unk1, dword_t unk2, dword_t unk3, dword_t unk4, + lpdword_t out_unk5, dword_t overlapped_ptr) { *out_unk5 = 1; if (overlapped_ptr) { @@ -487,10 +455,10 @@ dword_result_t XamUserContentRestrictionCheckAccess(dword_t user_index, } DECLARE_XAM_EXPORT1(XamUserContentRestrictionCheckAccess, kUserProfiles, kStub); -dword_result_t XamUserIsOnlineEnabled(dword_t user_index) { return 1; } +dword_result_t XamUserIsOnlineEnabled_entry(dword_t user_index) { return 1; } DECLARE_XAM_EXPORT1(XamUserIsOnlineEnabled, kUserProfiles, kStub); -dword_result_t XamUserGetMembershipTier(dword_t user_index) { +dword_result_t XamUserGetMembershipTier_entry(dword_t user_index) { if (user_index >= 4) { return X_ERROR_INVALID_PARAMETER; } @@ -501,9 +469,9 @@ dword_result_t XamUserGetMembershipTier(dword_t user_index) { } DECLARE_XAM_EXPORT1(XamUserGetMembershipTier, kUserProfiles, kStub); -dword_result_t XamUserAreUsersFriends(dword_t user_index, dword_t unk1, - dword_t unk2, lpdword_t out_value, - dword_t overlapped_ptr) { +dword_result_t XamUserAreUsersFriends_entry(dword_t user_index, dword_t unk1, + dword_t unk2, lpdword_t out_value, + dword_t overlapped_ptr) { uint32_t are_friends = 0; X_RESULT result; @@ -545,7 +513,7 @@ dword_result_t XamUserAreUsersFriends(dword_t user_index, dword_t unk1, } DECLARE_XAM_EXPORT1(XamUserAreUsersFriends, kUserProfiles, kStub); -dword_result_t XamShowSigninUI(dword_t unk, dword_t unk_mask) { +dword_result_t XamShowSigninUI_entry(dword_t unk, dword_t unk_mask) { // Mask values vary. Probably matching user types? Local/remote? // To fix game modes that display a 4 profile signin UI (even if playing @@ -676,12 +644,10 @@ class XStaticAchievementEnumerator : public XEnumerator { size_t current_item_ = 0; }; -dword_result_t XamUserCreateAchievementEnumerator(dword_t title_id, - dword_t user_index, - dword_t xuid, dword_t flags, - dword_t offset, dword_t count, - lpdword_t buffer_size_ptr, - lpdword_t handle_ptr) { +dword_result_t XamUserCreateAchievementEnumerator_entry( + dword_t title_id, dword_t user_index, dword_t xuid, dword_t flags, + dword_t offset, dword_t count, lpdword_t buffer_size_ptr, + lpdword_t handle_ptr) { if (!count || !buffer_size_ptr || !handle_ptr) { return X_ERROR_INVALID_PARAMETER; } @@ -727,8 +693,9 @@ dword_result_t XamUserCreateAchievementEnumerator(dword_t title_id, DECLARE_XAM_EXPORT1(XamUserCreateAchievementEnumerator, kUserProfiles, kSketchy); -dword_result_t XamParseGamerTileKey(lpdword_t key_ptr, lpdword_t out1_ptr, - lpdword_t out2_ptr, lpdword_t out3_ptr) { +dword_result_t XamParseGamerTileKey_entry(lpdword_t key_ptr, lpdword_t out1_ptr, + lpdword_t out2_ptr, + lpdword_t out3_ptr) { *out1_ptr = 0xC0DE0001; *out2_ptr = 0xC0DE0002; *out3_ptr = 0xC0DE0003; @@ -736,10 +703,11 @@ dword_result_t XamParseGamerTileKey(lpdword_t key_ptr, lpdword_t out1_ptr, } DECLARE_XAM_EXPORT1(XamParseGamerTileKey, kUserProfiles, kStub); -dword_result_t XamReadTileToTexture(dword_t unknown, dword_t title_id, - qword_t tile_id, dword_t user_index, - lpvoid_t buffer_ptr, dword_t stride, - dword_t height, dword_t overlapped_ptr) { +dword_result_t XamReadTileToTexture_entry(dword_t unknown, dword_t title_id, + qword_t tile_id, dword_t user_index, + lpvoid_t buffer_ptr, dword_t stride, + dword_t height, + dword_t overlapped_ptr) { // TODO(gibbed): unknown=0,2,3,9 if (!tile_id) { return X_ERROR_INVALID_PARAMETER; @@ -757,9 +725,9 @@ dword_result_t XamReadTileToTexture(dword_t unknown, dword_t title_id, } DECLARE_XAM_EXPORT1(XamReadTileToTexture, kUserProfiles, kStub); -dword_result_t XamWriteGamerTile(dword_t arg1, dword_t arg2, dword_t arg3, - dword_t arg4, dword_t arg5, - dword_t overlapped_ptr) { +dword_result_t XamWriteGamerTile_entry(dword_t arg1, dword_t arg2, dword_t arg3, + dword_t arg4, dword_t arg5, + dword_t overlapped_ptr) { if (overlapped_ptr) { kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS); @@ -769,13 +737,14 @@ dword_result_t XamWriteGamerTile(dword_t arg1, dword_t arg2, dword_t arg3, } DECLARE_XAM_EXPORT1(XamWriteGamerTile, kUserProfiles, kStub); -dword_result_t XamSessionCreateHandle(lpdword_t handle_ptr) { +dword_result_t XamSessionCreateHandle_entry(lpdword_t handle_ptr) { *handle_ptr = 0xCAFEDEAD; return X_ERROR_SUCCESS; } DECLARE_XAM_EXPORT1(XamSessionCreateHandle, kUserProfiles, kStub); -dword_result_t XamSessionRefObjByHandle(dword_t handle, lpdword_t obj_ptr) { +dword_result_t XamSessionRefObjByHandle_entry(dword_t handle, + lpdword_t obj_ptr) { assert_true(handle == 0xCAFEDEAD); // TODO(PermaNull): Implement this properly, // For the time being returning 0xDEADF00D will prevent crashing. @@ -788,5 +757,4 @@ DECLARE_XAM_EXPORT1(XamSessionRefObjByHandle, kUserProfiles, kStub); } // namespace kernel } // namespace xe -void xe::kernel::xam::RegisterUserExports( - xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {} +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(User); diff --git a/src/xenia/kernel/xam/xam_video.cc b/src/xenia/kernel/xam/xam_video.cc index 8cdf63869..37c9d6948 100644 --- a/src/xenia/kernel/xam/xam_video.cc +++ b/src/xenia/kernel/xam/xam_video.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,18 +18,17 @@ namespace xe { namespace kernel { namespace xam { -void XGetVideoMode(pointer_t video_mode) { +void XGetVideoMode_entry(pointer_t video_mode) { // TODO(benvanik): actually check to see if these are the same. xboxkrnl::VdQueryVideoMode(std::move(video_mode)); } DECLARE_XAM_EXPORT1(XGetVideoMode, kVideo, ExportTag::kSketchy); -dword_result_t XGetVideoCapabilities() { return 0; } +dword_result_t XGetVideoCapabilities_entry() { return 0; } DECLARE_XAM_EXPORT1(XGetVideoCapabilities, kVideo, kStub); -void RegisterVideoExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Video); diff --git a/src/xenia/kernel/xam/xam_voice.cc b/src/xenia/kernel/xam/xam_voice.cc index 2cd70b2ca..dbe87db3d 100644 --- a/src/xenia/kernel/xam/xam_voice.cc +++ b/src/xenia/kernel/xam/xam_voice.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,30 +17,29 @@ namespace xe { namespace kernel { namespace xam { -dword_result_t XamVoiceIsActiveProcess() { +dword_result_t XamVoiceIsActiveProcess_entry() { // Returning 0 here will short-circuit a bunch of voice stuff. return 0; } DECLARE_XAM_EXPORT1(XamVoiceIsActiveProcess, kNone, kStub); -dword_result_t XamVoiceCreate(unknown_t unk1, // 0 - unknown_t unk2, // 0xF - lpdword_t out_voice_ptr) { +dword_result_t XamVoiceCreate_entry(unknown_t unk1, // 0 + unknown_t unk2, // 0xF + lpdword_t out_voice_ptr) { // Null out the ptr. out_voice_ptr.Zero(); return X_ERROR_ACCESS_DENIED; } DECLARE_XAM_EXPORT1(XamVoiceCreate, kNone, kStub); -dword_result_t XamVoiceClose(lpunknown_t voice_ptr) { return 0; } +dword_result_t XamVoiceClose_entry(lpunknown_t voice_ptr) { return 0; } DECLARE_XAM_EXPORT1(XamVoiceClose, kNone, kStub); -dword_result_t XamVoiceHeadsetPresent(lpunknown_t voice_ptr) { return 0; } +dword_result_t XamVoiceHeadsetPresent_entry(lpunknown_t voice_ptr) { return 0; } DECLARE_XAM_EXPORT1(XamVoiceHeadsetPresent, kNone, kStub); -void RegisterVoiceExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xam } // namespace kernel } // namespace xe + +DECLARE_XAM_EMPTY_REGISTER_EXPORTS(Voice); diff --git a/src/xenia/kernel/xbdm/xbdm_misc.cc b/src/xenia/kernel/xbdm/xbdm_misc.cc index e15af9eb6..7f2b9f960 100644 --- a/src/xenia/kernel/xbdm/xbdm_misc.cc +++ b/src/xenia/kernel/xbdm/xbdm_misc.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,22 +18,22 @@ namespace xe { namespace kernel { namespace xbdm { -#define MAKE_DUMMY_STUB_PTR(x) \ - dword_result_t x() { return 0; } \ +#define MAKE_DUMMY_STUB_PTR(x) \ + dword_result_t x##_entry() { return 0; } \ DECLARE_XBDM_EXPORT1(x, kDebug, kStub) -#define MAKE_DUMMY_STUB_STATUS(x) \ - dword_result_t x() { return X_STATUS_INVALID_PARAMETER; } \ +#define MAKE_DUMMY_STUB_STATUS(x) \ + dword_result_t x##_entry() { return X_STATUS_INVALID_PARAMETER; } \ DECLARE_XBDM_EXPORT1(x, kDebug, kStub) MAKE_DUMMY_STUB_PTR(DmAllocatePool); -void DmCloseLoadedModules(lpdword_t unk0_ptr) {} +void DmCloseLoadedModules_entry(lpdword_t unk0_ptr) {} DECLARE_XBDM_EXPORT1(DmCloseLoadedModules, kDebug, kStub); MAKE_DUMMY_STUB_STATUS(DmFreePool); -dword_result_t DmGetXbeInfo() { +dword_result_t DmGetXbeInfo_entry() { // TODO(gibbed): 4D5307DC appears to expect this as success? // Unknown arguments -- let's hope things don't explode. return 0x02DA0000; @@ -42,17 +42,17 @@ DECLARE_XBDM_EXPORT1(DmGetXbeInfo, kDebug, kStub); MAKE_DUMMY_STUB_STATUS(DmGetXboxName); -dword_result_t DmIsDebuggerPresent() { return 0; } +dword_result_t DmIsDebuggerPresent_entry() { return 0; } DECLARE_XBDM_EXPORT1(DmIsDebuggerPresent, kDebug, kStub); MAKE_DUMMY_STUB_STATUS(DmRegisterCommandProcessor); -void DmSendNotificationString(lpdword_t unk0_ptr) {} +void DmSendNotificationString_entry(lpdword_t unk0_ptr) {} DECLARE_XBDM_EXPORT1(DmSendNotificationString, kDebug, kStub); -dword_result_t DmRegisterCommandProcessorEx(lpdword_t name_ptr, - lpdword_t handler_fn, - dword_t unk3) { +dword_result_t DmRegisterCommandProcessorEx_entry(lpdword_t name_ptr, + lpdword_t handler_fn, + dword_t unk3) { // Return success to prevent some games from stalling return X_STATUS_SUCCESS; } @@ -61,7 +61,8 @@ DECLARE_XBDM_EXPORT1(DmRegisterCommandProcessorEx, kDebug, kStub); MAKE_DUMMY_STUB_STATUS(DmStartProfiling); MAKE_DUMMY_STUB_STATUS(DmStopProfiling); -dword_result_t DmCaptureStackBackTrace(lpdword_t unk0_ptr, lpdword_t unk1_ptr) { +dword_result_t DmCaptureStackBackTrace_entry(lpdword_t unk0_ptr, + lpdword_t unk1_ptr) { return X_STATUS_INVALID_PARAMETER; } DECLARE_XBDM_EXPORT1(DmCaptureStackBackTrace, kDebug, kStub); @@ -69,23 +70,24 @@ DECLARE_XBDM_EXPORT1(DmCaptureStackBackTrace, kDebug, kStub); MAKE_DUMMY_STUB_STATUS(DmGetThreadInfoEx); MAKE_DUMMY_STUB_STATUS(DmSetProfilingOptions); -dword_result_t DmWalkLoadedModules(lpdword_t unk0_ptr, lpdword_t unk1_ptr) { +dword_result_t DmWalkLoadedModules_entry(lpdword_t unk0_ptr, + lpdword_t unk1_ptr) { // Some games will loop forever unless this code is returned return 0x82DA0104; } DECLARE_XBDM_EXPORT1(DmWalkLoadedModules, kDebug, kStub); -void DmMapDevkitDrive() {} +void DmMapDevkitDrive_entry() {} DECLARE_XBDM_EXPORT1(DmMapDevkitDrive, kDebug, kStub); -dword_result_t DmFindPdbSignature(lpdword_t unk0_ptr, lpdword_t unk1_ptr) { +dword_result_t DmFindPdbSignature_entry(lpdword_t unk0_ptr, + lpdword_t unk1_ptr) { return X_STATUS_INVALID_PARAMETER; } DECLARE_XBDM_EXPORT1(DmFindPdbSignature, kDebug, kStub); -void RegisterMiscExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xbdm } // namespace kernel } // namespace xe + +DECLARE_XBDM_EMPTY_REGISTER_EXPORTS(Misc); diff --git a/src/xenia/kernel/xbdm/xbdm_module.cc b/src/xenia/kernel/xbdm/xbdm_module.cc index 5e22aae43..c744e4b68 100644 --- a/src/xenia/kernel/xbdm/xbdm_module.cc +++ b/src/xenia/kernel/xbdm/xbdm_module.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -24,7 +24,10 @@ XbdmModule::XbdmModule(Emulator* emulator, KernelState* kernel_state) RegisterExportTable(export_resolver_); // Register all exported functions. - RegisterMiscExports(export_resolver_, kernel_state_); +#define XE_MODULE_EXPORT_GROUP(m, n) \ + Register##n##Exports(export_resolver_, kernel_state_); +#include "xbdm_module_export_groups.inc" +#undef XE_MODULE_EXPORT_GROUP } std::vector xbdm_exports(4096); diff --git a/src/xenia/hid/input_driver.cc b/src/xenia/kernel/xbdm/xbdm_module_export_groups.inc similarity index 60% rename from src/xenia/hid/input_driver.cc rename to src/xenia/kernel/xbdm/xbdm_module_export_groups.inc index 1627d5dc4..f47842d3d 100644 --- a/src/xenia/hid/input_driver.cc +++ b/src/xenia/kernel/xbdm/xbdm_module_export_groups.inc @@ -2,19 +2,12 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ -#include "xenia/hid/input_driver.h" +// This is a partial file designed to be included by other files when +// constructing various tables. -namespace xe { -namespace hid { - -InputDriver::InputDriver(xe::ui::Window* window) : window_(window) {} - -InputDriver::~InputDriver() = default; - -} // namespace hid -} // namespace xe +XE_MODULE_EXPORT_GROUP(xbdm, Misc) diff --git a/src/xenia/kernel/xbdm/xbdm_private.h b/src/xenia/kernel/xbdm/xbdm_private.h index 3f8619204..9c2e70515 100644 --- a/src/xenia/kernel/xbdm/xbdm_private.h +++ b/src/xenia/kernel/xbdm/xbdm_private.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -21,8 +21,11 @@ namespace xbdm { xe::cpu::Export* RegisterExport_xbdm(xe::cpu::Export* export_entry); // Registration functions, one per file. -void RegisterMiscExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state); +#define XE_MODULE_EXPORT_GROUP(m, n) \ + void Register##n##Exports(xe::cpu::ExportResolver* export_resolver, \ + KernelState* kernel_state); +#include "xbdm_module_export_groups.inc" +#undef XE_MODULE_EXPORT_GROUP } // namespace xbdm } // namespace kernel diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc index d9c861211..3e9c39cbd 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -19,14 +19,14 @@ namespace xe { namespace kernel { namespace xboxkrnl { -dword_result_t XAudioGetSpeakerConfig(lpdword_t config_ptr) { +dword_result_t XAudioGetSpeakerConfig_entry(lpdword_t config_ptr) { *config_ptr = 0x00010001; return X_ERROR_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(XAudioGetSpeakerConfig, kAudio, kImplemented); -dword_result_t XAudioGetVoiceCategoryVolumeChangeMask(lpunknown_t driver_ptr, - lpdword_t out_ptr) { +dword_result_t XAudioGetVoiceCategoryVolumeChangeMask_entry( + lpunknown_t driver_ptr, lpdword_t out_ptr) { assert_true((driver_ptr.guest_address() & 0xFFFF0000) == 0x41550000); xe::threading::MaybeYield(); @@ -39,7 +39,8 @@ dword_result_t XAudioGetVoiceCategoryVolumeChangeMask(lpunknown_t driver_ptr, DECLARE_XBOXKRNL_EXPORT2(XAudioGetVoiceCategoryVolumeChangeMask, kAudio, kStub, kHighFrequency); -dword_result_t XAudioGetVoiceCategoryVolume(dword_t unk, lpfloat_t out_ptr) { +dword_result_t XAudioGetVoiceCategoryVolume_entry(dword_t unk, + lpfloat_t out_ptr) { // Expects a floating point single. Volume %? *out_ptr = 1.0f; @@ -48,11 +49,11 @@ dword_result_t XAudioGetVoiceCategoryVolume(dword_t unk, lpfloat_t out_ptr) { DECLARE_XBOXKRNL_EXPORT2(XAudioGetVoiceCategoryVolume, kAudio, kStub, kHighFrequency); -dword_result_t XAudioEnableDucker(dword_t unk) { return X_ERROR_SUCCESS; } +dword_result_t XAudioEnableDucker_entry(dword_t unk) { return X_ERROR_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(XAudioEnableDucker, kAudio, kStub); -dword_result_t XAudioRegisterRenderDriverClient(lpdword_t callback_ptr, - lpdword_t driver_ptr) { +dword_result_t XAudioRegisterRenderDriverClient_entry(lpdword_t callback_ptr, + lpdword_t driver_ptr) { uint32_t callback = callback_ptr[0]; uint32_t callback_arg = callback_ptr[1]; @@ -71,7 +72,8 @@ dword_result_t XAudioRegisterRenderDriverClient(lpdword_t callback_ptr, DECLARE_XBOXKRNL_EXPORT1(XAudioRegisterRenderDriverClient, kAudio, kImplemented); -dword_result_t XAudioUnregisterRenderDriverClient(lpunknown_t driver_ptr) { +dword_result_t XAudioUnregisterRenderDriverClient_entry( + lpunknown_t driver_ptr) { assert_true((driver_ptr.guest_address() & 0xFFFF0000) == 0x41550000); auto audio_system = kernel_state()->emulator()->audio_system(); @@ -81,8 +83,8 @@ dword_result_t XAudioUnregisterRenderDriverClient(lpunknown_t driver_ptr) { DECLARE_XBOXKRNL_EXPORT1(XAudioUnregisterRenderDriverClient, kAudio, kImplemented); -dword_result_t XAudioSubmitRenderDriverFrame(lpunknown_t driver_ptr, - lpunknown_t samples_ptr) { +dword_result_t XAudioSubmitRenderDriverFrame_entry(lpunknown_t driver_ptr, + lpunknown_t samples_ptr) { assert_true((driver_ptr.guest_address() & 0xFFFF0000) == 0x41550000); auto audio_system = kernel_state()->emulator()->audio_system(); @@ -94,11 +96,8 @@ dword_result_t XAudioSubmitRenderDriverFrame(lpunknown_t driver_ptr, DECLARE_XBOXKRNL_EXPORT2(XAudioSubmitRenderDriverFrame, kAudio, kImplemented, kHighFrequency); -void RegisterAudioExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) { - // Additional XMA* methods are in xboxkrnl_audio_xma.cc. -} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Audio); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc index f4c2c156e..66e988ea0 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -58,7 +58,7 @@ using xe::apu::XMA_CONTEXT_DATA; // restrictions of frame/subframe/etc: // https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xaudio2.xaudio2_buffer(v=vs.85).aspx -dword_result_t XMACreateContext(lpdword_t context_out_ptr) { +dword_result_t XMACreateContext_entry(lpdword_t context_out_ptr) { auto xma_decoder = kernel_state()->emulator()->audio_system()->xma_decoder(); uint32_t context_ptr = xma_decoder->AllocateContext(); *context_out_ptr = context_ptr; @@ -70,7 +70,7 @@ dword_result_t XMACreateContext(lpdword_t context_out_ptr) { DECLARE_XBOXKRNL_EXPORT2(XMACreateContext, kAudio, kImplemented, kHighFrequency); -dword_result_t XMAReleaseContext(lpvoid_t context_ptr) { +dword_result_t XMAReleaseContext_entry(lpvoid_t context_ptr) { auto xma_decoder = kernel_state()->emulator()->audio_system()->xma_decoder(); xma_decoder->ReleaseContext(context_ptr); return 0; @@ -117,8 +117,8 @@ struct XMA_CONTEXT_INIT { }; static_assert_size(XMA_CONTEXT_INIT, 56); -dword_result_t XMAInitializeContext(lpvoid_t context_ptr, - pointer_t context_init) { +dword_result_t XMAInitializeContext_entry( + lpvoid_t context_ptr, pointer_t context_init) { // Input buffers may be null (buffer 1 in 415607D4). // Convert to host endianness. uint32_t input_buffer_0_guest_ptr = context_init->input_buffer_0_ptr; @@ -193,8 +193,8 @@ dword_result_t XMAInitializeContext(lpvoid_t context_ptr, DECLARE_XBOXKRNL_EXPORT2(XMAInitializeContext, kAudio, kImplemented, kHighFrequency); -dword_result_t XMASetLoopData(lpvoid_t context_ptr, - pointer_t loop_data) { +dword_result_t XMASetLoopData_entry(lpvoid_t context_ptr, + pointer_t loop_data) { XMA_CONTEXT_DATA context(context_ptr); context.loop_start = loop_data->loop_start; @@ -209,15 +209,15 @@ dword_result_t XMASetLoopData(lpvoid_t context_ptr, } DECLARE_XBOXKRNL_EXPORT2(XMASetLoopData, kAudio, kImplemented, kHighFrequency); -dword_result_t XMAGetInputBufferReadOffset(lpvoid_t context_ptr) { +dword_result_t XMAGetInputBufferReadOffset_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); return context.input_buffer_read_offset; } DECLARE_XBOXKRNL_EXPORT2(XMAGetInputBufferReadOffset, kAudio, kImplemented, kHighFrequency); -dword_result_t XMASetInputBufferReadOffset(lpvoid_t context_ptr, - dword_t value) { +dword_result_t XMASetInputBufferReadOffset_entry(lpvoid_t context_ptr, + dword_t value) { XMA_CONTEXT_DATA context(context_ptr); context.input_buffer_read_offset = value; context.Store(context_ptr); @@ -227,8 +227,8 @@ dword_result_t XMASetInputBufferReadOffset(lpvoid_t context_ptr, DECLARE_XBOXKRNL_EXPORT2(XMASetInputBufferReadOffset, kAudio, kImplemented, kHighFrequency); -dword_result_t XMASetInputBuffer0(lpvoid_t context_ptr, lpvoid_t buffer, - dword_t packet_count) { +dword_result_t XMASetInputBuffer0_entry(lpvoid_t context_ptr, lpvoid_t buffer, + dword_t packet_count) { uint32_t buffer_physical_address = kernel_memory()->GetPhysicalAddress(buffer.guest_address()); assert_true(buffer_physical_address != UINT32_MAX); @@ -251,14 +251,14 @@ dword_result_t XMASetInputBuffer0(lpvoid_t context_ptr, lpvoid_t buffer, DECLARE_XBOXKRNL_EXPORT2(XMASetInputBuffer0, kAudio, kImplemented, kHighFrequency); -dword_result_t XMAIsInputBuffer0Valid(lpvoid_t context_ptr) { +dword_result_t XMAIsInputBuffer0Valid_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); return context.input_buffer_0_valid; } DECLARE_XBOXKRNL_EXPORT2(XMAIsInputBuffer0Valid, kAudio, kImplemented, kHighFrequency); -dword_result_t XMASetInputBuffer0Valid(lpvoid_t context_ptr) { +dword_result_t XMASetInputBuffer0Valid_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); context.input_buffer_0_valid = 1; context.Store(context_ptr); @@ -268,8 +268,8 @@ dword_result_t XMASetInputBuffer0Valid(lpvoid_t context_ptr) { DECLARE_XBOXKRNL_EXPORT2(XMASetInputBuffer0Valid, kAudio, kImplemented, kHighFrequency); -dword_result_t XMASetInputBuffer1(lpvoid_t context_ptr, lpvoid_t buffer, - dword_t packet_count) { +dword_result_t XMASetInputBuffer1_entry(lpvoid_t context_ptr, lpvoid_t buffer, + dword_t packet_count) { uint32_t buffer_physical_address = kernel_memory()->GetPhysicalAddress(buffer.guest_address()); assert_true(buffer_physical_address != UINT32_MAX); @@ -292,14 +292,14 @@ dword_result_t XMASetInputBuffer1(lpvoid_t context_ptr, lpvoid_t buffer, DECLARE_XBOXKRNL_EXPORT2(XMASetInputBuffer1, kAudio, kImplemented, kHighFrequency); -dword_result_t XMAIsInputBuffer1Valid(lpvoid_t context_ptr) { +dword_result_t XMAIsInputBuffer1Valid_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); return context.input_buffer_1_valid; } DECLARE_XBOXKRNL_EXPORT2(XMAIsInputBuffer1Valid, kAudio, kImplemented, kHighFrequency); -dword_result_t XMASetInputBuffer1Valid(lpvoid_t context_ptr) { +dword_result_t XMASetInputBuffer1Valid_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); context.input_buffer_1_valid = 1; context.Store(context_ptr); @@ -309,14 +309,14 @@ dword_result_t XMASetInputBuffer1Valid(lpvoid_t context_ptr) { DECLARE_XBOXKRNL_EXPORT2(XMASetInputBuffer1Valid, kAudio, kImplemented, kHighFrequency); -dword_result_t XMAIsOutputBufferValid(lpvoid_t context_ptr) { +dword_result_t XMAIsOutputBufferValid_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); return context.output_buffer_valid; } DECLARE_XBOXKRNL_EXPORT2(XMAIsOutputBufferValid, kAudio, kImplemented, kHighFrequency); -dword_result_t XMASetOutputBufferValid(lpvoid_t context_ptr) { +dword_result_t XMASetOutputBufferValid_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); context.output_buffer_valid = 1; context.Store(context_ptr); @@ -326,15 +326,15 @@ dword_result_t XMASetOutputBufferValid(lpvoid_t context_ptr) { DECLARE_XBOXKRNL_EXPORT2(XMASetOutputBufferValid, kAudio, kImplemented, kHighFrequency); -dword_result_t XMAGetOutputBufferReadOffset(lpvoid_t context_ptr) { +dword_result_t XMAGetOutputBufferReadOffset_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); return context.output_buffer_read_offset; } DECLARE_XBOXKRNL_EXPORT2(XMAGetOutputBufferReadOffset, kAudio, kImplemented, kHighFrequency); -dword_result_t XMASetOutputBufferReadOffset(lpvoid_t context_ptr, - dword_t value) { +dword_result_t XMASetOutputBufferReadOffset_entry(lpvoid_t context_ptr, + dword_t value) { XMA_CONTEXT_DATA context(context_ptr); context.output_buffer_read_offset = value; context.Store(context_ptr); @@ -344,27 +344,27 @@ dword_result_t XMASetOutputBufferReadOffset(lpvoid_t context_ptr, DECLARE_XBOXKRNL_EXPORT2(XMASetOutputBufferReadOffset, kAudio, kImplemented, kHighFrequency); -dword_result_t XMAGetOutputBufferWriteOffset(lpvoid_t context_ptr) { +dword_result_t XMAGetOutputBufferWriteOffset_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); return context.output_buffer_write_offset; } DECLARE_XBOXKRNL_EXPORT2(XMAGetOutputBufferWriteOffset, kAudio, kImplemented, kHighFrequency); -dword_result_t XMAGetPacketMetadata(lpvoid_t context_ptr) { +dword_result_t XMAGetPacketMetadata_entry(lpvoid_t context_ptr) { XMA_CONTEXT_DATA context(context_ptr); return context.packet_metadata; } DECLARE_XBOXKRNL_EXPORT1(XMAGetPacketMetadata, kAudio, kImplemented); -dword_result_t XMAEnableContext(lpvoid_t context_ptr) { +dword_result_t XMAEnableContext_entry(lpvoid_t context_ptr) { StoreXmaContextIndexedRegister(kernel_state(), 0x1940, context_ptr); return 0; } DECLARE_XBOXKRNL_EXPORT2(XMAEnableContext, kAudio, kImplemented, kHighFrequency); -dword_result_t XMADisableContext(lpvoid_t context_ptr, dword_t wait) { +dword_result_t XMADisableContext_entry(lpvoid_t context_ptr, dword_t wait) { X_HRESULT result = X_E_SUCCESS; StoreXmaContextIndexedRegister(kernel_state(), 0x1A40, context_ptr); if (!kernel_state() @@ -379,7 +379,7 @@ dword_result_t XMADisableContext(lpvoid_t context_ptr, dword_t wait) { DECLARE_XBOXKRNL_EXPORT2(XMADisableContext, kAudio, kImplemented, kHighFrequency); -dword_result_t XMABlockWhileInUse(lpvoid_t context_ptr) { +dword_result_t XMABlockWhileInUse_entry(lpvoid_t context_ptr) { do { XMA_CONTEXT_DATA context(context_ptr); if (!context.input_buffer_0_valid && !context.input_buffer_1_valid) { @@ -392,9 +392,8 @@ dword_result_t XMABlockWhileInUse(lpvoid_t context_ptr) { DECLARE_XBOXKRNL_EXPORT2(XMABlockWhileInUse, kAudio, kImplemented, kHighFrequency); -void RegisterAudioXmaExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(AudioXma); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc index 4dbc217a6..6d98bc01d 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** -* Copyright 2015 Ben Vanik. All rights reserved. * +* Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -43,8 +43,8 @@ typedef struct { } XECRYPT_RC4_STATE; static_assert_size(XECRYPT_RC4_STATE, 0x102); -void XeCryptRc4Key(pointer_t rc4_ctx, lpvoid_t key, - dword_t key_size) { +void XeCryptRc4Key_entry(pointer_t rc4_ctx, lpvoid_t key, + dword_t key_size) { // Setup RC4 state rc4_ctx->i = rc4_ctx->j = 0; for (uint32_t x = 0; x < 0x100; x++) { @@ -61,8 +61,8 @@ void XeCryptRc4Key(pointer_t rc4_ctx, lpvoid_t key, } DECLARE_XBOXKRNL_EXPORT1(XeCryptRc4Key, kNone, kImplemented); -void XeCryptRc4Ecb(pointer_t rc4_ctx, lpvoid_t data, - dword_t size) { +void XeCryptRc4Ecb_entry(pointer_t rc4_ctx, lpvoid_t data, + dword_t size) { // Crypt data for (uint32_t idx = 0; idx < size; idx++) { rc4_ctx->i = (rc4_ctx->i + 1) % 0x100; @@ -79,10 +79,11 @@ void XeCryptRc4Ecb(pointer_t rc4_ctx, lpvoid_t data, } DECLARE_XBOXKRNL_EXPORT1(XeCryptRc4Ecb, kNone, kImplemented); -void XeCryptRc4(lpvoid_t key, dword_t key_size, lpvoid_t data, dword_t size) { +void XeCryptRc4_entry(lpvoid_t key, dword_t key_size, lpvoid_t data, + dword_t size) { XECRYPT_RC4_STATE rc4_ctx; - XeCryptRc4Key(&rc4_ctx, key, key_size); - XeCryptRc4Ecb(&rc4_ctx, data, size); + XeCryptRc4Key_entry(&rc4_ctx, key, key_size); + XeCryptRc4Ecb_entry(&rc4_ctx, data, size); } DECLARE_XBOXKRNL_EXPORT1(XeCryptRc4, kNone, kImplemented); @@ -107,7 +108,7 @@ void StoreSha1(const sha1::SHA1* sha, XECRYPT_SHA_STATE* state) { std::copy_n(sha->getBlock(), sha->getBlockByteIndex(), state->buffer); } -void XeCryptShaInit(pointer_t sha_state) { +void XeCryptShaInit_entry(pointer_t sha_state) { sha_state.Zero(); sha_state->state[0] = 0x67452301; @@ -118,8 +119,8 @@ void XeCryptShaInit(pointer_t sha_state) { } DECLARE_XBOXKRNL_EXPORT1(XeCryptShaInit, kNone, kImplemented); -void XeCryptShaUpdate(pointer_t sha_state, lpvoid_t input, - dword_t input_size) { +void XeCryptShaUpdate_entry(pointer_t sha_state, + lpvoid_t input, dword_t input_size) { sha1::SHA1 sha; InitSha1(&sha, sha_state); @@ -129,8 +130,8 @@ void XeCryptShaUpdate(pointer_t sha_state, lpvoid_t input, } DECLARE_XBOXKRNL_EXPORT1(XeCryptShaUpdate, kNone, kImplemented); -void XeCryptShaFinal(pointer_t sha_state, - pointer_t out, dword_t out_size) { +void XeCryptShaFinal_entry(pointer_t sha_state, + pointer_t out, dword_t out_size) { sha1::SHA1 sha; InitSha1(&sha, sha_state); @@ -143,9 +144,10 @@ void XeCryptShaFinal(pointer_t sha_state, } DECLARE_XBOXKRNL_EXPORT1(XeCryptShaFinal, kNone, kImplemented); -void XeCryptSha(lpvoid_t input_1, dword_t input_1_size, lpvoid_t input_2, - dword_t input_2_size, lpvoid_t input_3, dword_t input_3_size, - lpvoid_t output, dword_t output_size) { +void XeCryptSha_entry(lpvoid_t input_1, dword_t input_1_size, lpvoid_t input_2, + dword_t input_2_size, lpvoid_t input_3, + dword_t input_3_size, lpvoid_t output, + dword_t output_size) { sha1::SHA1 sha; if (input_1 && input_1_size) { @@ -172,7 +174,7 @@ typedef struct { uint8_t buffer[64]; // 0x24 } XECRYPT_SHA256_STATE; -void XeCryptSha256Init(pointer_t sha_state) { +void XeCryptSha256Init_entry(pointer_t sha_state) { sha_state.Zero(); sha_state->state[0] = 0x6a09e667; @@ -186,8 +188,8 @@ void XeCryptSha256Init(pointer_t sha_state) { } DECLARE_XBOXKRNL_EXPORT1(XeCryptSha256Init, kNone, kImplemented); -void XeCryptSha256Update(pointer_t sha_state, - lpvoid_t input, dword_t input_size) { +void XeCryptSha256Update_entry(pointer_t sha_state, + lpvoid_t input, dword_t input_size) { sha256::SHA256 sha; std::copy(std::begin(sha_state->state), std::end(sha_state->state), sha.getHashValues()); @@ -205,8 +207,8 @@ void XeCryptSha256Update(pointer_t sha_state, } DECLARE_XBOXKRNL_EXPORT1(XeCryptSha256Update, kNone, kImplemented); -void XeCryptSha256Final(pointer_t sha_state, - pointer_t out, dword_t out_size) { +void XeCryptSha256Final_entry(pointer_t sha_state, + pointer_t out, dword_t out_size) { sha256::SHA256 sha; std::copy(std::begin(sha_state->state), std::end(sha_state->state), sha.getHashValues()); @@ -224,8 +226,8 @@ void XeCryptSha256Final(pointer_t sha_state, DECLARE_XBOXKRNL_EXPORT1(XeCryptSha256Final, kNone, kImplemented); // Byteswaps each 8 bytes -void XeCryptBnQw_SwapDwQwLeBe(pointer_t qw_inp, - pointer_t qw_out, dword_t size) { +void XeCryptBnQw_SwapDwQwLeBe_entry(pointer_t qw_inp, + pointer_t qw_out, dword_t size) { xe::copy_and_swap(qw_out, qw_inp, size); } DECLARE_XBOXKRNL_EXPORT1(XeCryptBnQw_SwapDwQwLeBe, kNone, kImplemented); @@ -239,9 +241,9 @@ typedef struct { } XECRYPT_RSA; static_assert_size(XECRYPT_RSA, 0x10); -dword_result_t XeCryptBnQwNeRsaPubCrypt(pointer_t qw_a, - pointer_t qw_b, - pointer_t rsa) { +dword_result_t XeCryptBnQwNeRsaPubCrypt_entry(pointer_t qw_a, + pointer_t qw_b, + pointer_t rsa) { // 0 indicates failure (but not a BOOL return value) #ifndef XE_PLATFORM_WIN32 XELOGE( @@ -342,14 +344,14 @@ DECLARE_XBOXKRNL_EXPORT1(XeCryptBnQwNeRsaPubCrypt, kNone, kImplemented); DECLARE_XBOXKRNL_EXPORT1(XeCryptBnQwNeRsaPubCrypt, kNone, kStub); #endif -dword_result_t XeCryptBnDwLePkcs1Verify(lpvoid_t hash, lpvoid_t sig, - dword_t size) { +dword_result_t XeCryptBnDwLePkcs1Verify_entry(lpvoid_t hash, lpvoid_t sig, + dword_t size) { // BOOL return value return 1; } DECLARE_XBOXKRNL_EXPORT1(XeCryptBnDwLePkcs1Verify, kNone, kStub); -void XeCryptRandom(lpvoid_t buf, dword_t buf_size) { +void XeCryptRandom_entry(lpvoid_t buf, dword_t buf_size) { std::memset(buf, 0xFD, buf_size); } DECLARE_XBOXKRNL_EXPORT1(XeCryptRandom, kNone, kStub); @@ -359,7 +361,7 @@ struct XECRYPT_DES_STATE { }; // Sets bit 0 to make the parity odd -void XeCryptDesParity(lpvoid_t inp, dword_t inp_size, lpvoid_t out_ptr) { +void XeCryptDesParity_entry(lpvoid_t inp, dword_t inp_size, lpvoid_t out_ptr) { DES::set_parity(inp, inp_size, out_ptr); } DECLARE_XBOXKRNL_EXPORT1(XeCryptDesParity, kNone, kImplemented); @@ -368,7 +370,8 @@ struct XECRYPT_DES3_STATE { XECRYPT_DES_STATE des_state[3]; }; -void XeCryptDes3Key(pointer_t state_ptr, lpqword_t key) { +void XeCryptDes3Key_entry(pointer_t state_ptr, + lpqword_t key) { DES3 des3(key[0], key[1], key[2]); DES* des = des3.getDES(); @@ -379,8 +382,8 @@ void XeCryptDes3Key(pointer_t state_ptr, lpqword_t key) { } DECLARE_XBOXKRNL_EXPORT1(XeCryptDes3Key, kNone, kImplemented); -void XeCryptDes3Ecb(pointer_t state_ptr, lpqword_t inp, - lpqword_t out, dword_t encrypt) { +void XeCryptDes3Ecb_entry(pointer_t state_ptr, + lpqword_t inp, lpqword_t out, dword_t encrypt) { DES3 des3((ui64*)state_ptr->des_state[0].keytab, (ui64*)state_ptr->des_state[1].keytab, (ui64*)state_ptr->des_state[2].keytab); @@ -393,9 +396,9 @@ void XeCryptDes3Ecb(pointer_t state_ptr, lpqword_t inp, } DECLARE_XBOXKRNL_EXPORT1(XeCryptDes3Ecb, kNone, kImplemented); -void XeCryptDes3Cbc(pointer_t state_ptr, lpqword_t inp, - dword_t inp_size, lpqword_t out, lpqword_t feed, - dword_t encrypt) { +void XeCryptDes3Cbc_entry(pointer_t state_ptr, + lpqword_t inp, dword_t inp_size, lpqword_t out, + lpqword_t feed, dword_t encrypt) { DES3 des3((ui64*)state_ptr->des_state[0].keytab, (ui64*)state_ptr->des_state[1].keytab, (ui64*)state_ptr->des_state[2].keytab); @@ -429,7 +432,7 @@ static inline uint8_t xeXeCryptAesMul2(uint8_t a) { return (a & 0x80) ? ((a << 1) ^ 0x1B) : (a << 1); } -void XeCryptAesKey(pointer_t state_ptr, lpvoid_t key) { +void XeCryptAesKey_entry(pointer_t state_ptr, lpvoid_t key) { aes_key_schedule_128(key, reinterpret_cast(state_ptr->keytabenc)); // Decryption key schedule not needed by openluopworld/aes_128, but generated // to fill the context structure properly. @@ -494,8 +497,8 @@ void XeCryptAesKey(pointer_t state_ptr, lpvoid_t key) { } DECLARE_XBOXKRNL_EXPORT1(XeCryptAesKey, kNone, kImplemented); -void XeCryptAesEcb(pointer_t state_ptr, lpvoid_t inp_ptr, - lpvoid_t out_ptr, dword_t encrypt) { +void XeCryptAesEcb_entry(pointer_t state_ptr, + lpvoid_t inp_ptr, lpvoid_t out_ptr, dword_t encrypt) { const uint8_t* keytab = reinterpret_cast(state_ptr->keytabenc); if (encrypt) { @@ -506,9 +509,9 @@ void XeCryptAesEcb(pointer_t state_ptr, lpvoid_t inp_ptr, } DECLARE_XBOXKRNL_EXPORT1(XeCryptAesEcb, kNone, kImplemented); -void XeCryptAesCbc(pointer_t state_ptr, lpvoid_t inp_ptr, - dword_t inp_size, lpvoid_t out_ptr, lpvoid_t feed_ptr, - dword_t encrypt) { +void XeCryptAesCbc_entry(pointer_t state_ptr, + lpvoid_t inp_ptr, dword_t inp_size, lpvoid_t out_ptr, + lpvoid_t feed_ptr, dword_t encrypt) { const uint8_t* keytab = reinterpret_cast(state_ptr->keytabenc); const uint8_t* inp = inp_ptr.as(); @@ -541,10 +544,10 @@ void XeCryptAesCbc(pointer_t state_ptr, lpvoid_t inp_ptr, } DECLARE_XBOXKRNL_EXPORT1(XeCryptAesCbc, kNone, kImplemented); -void XeCryptHmacSha(lpvoid_t key, dword_t key_size_in, lpvoid_t inp_1, - dword_t inp_1_size, lpvoid_t inp_2, dword_t inp_2_size, - lpvoid_t inp_3, dword_t inp_3_size, lpvoid_t out, - dword_t out_size) { +void XeCryptHmacSha_entry(lpvoid_t key, dword_t key_size_in, lpvoid_t inp_1, + dword_t inp_1_size, lpvoid_t inp_2, + dword_t inp_2_size, lpvoid_t inp_3, + dword_t inp_3_size, lpvoid_t out, dword_t out_size) { uint32_t key_size = key_size_in; sha1::SHA1 sha; uint8_t kpad_i[0x40]; @@ -605,19 +608,19 @@ DECLARE_XBOXKRNL_EXPORT1(XeCryptHmacSha, kNone, kImplemented); static const uint8_t key19[] = {0xE1, 0xBC, 0x15, 0x9C, 0x73, 0xB1, 0xEA, 0xE9, 0xAB, 0x31, 0x70, 0xF3, 0xAD, 0x47, 0xEB, 0xF3}; -dword_result_t XeKeysHmacSha(dword_t key_num, lpvoid_t inp_1, - dword_t inp_1_size, lpvoid_t inp_2, - dword_t inp_2_size, lpvoid_t inp_3, - dword_t inp_3_size, lpvoid_t out, - dword_t out_size) { +dword_result_t XeKeysHmacSha_entry(dword_t key_num, lpvoid_t inp_1, + dword_t inp_1_size, lpvoid_t inp_2, + dword_t inp_2_size, lpvoid_t inp_3, + dword_t inp_3_size, lpvoid_t out, + dword_t out_size) { const uint8_t* key = nullptr; if (key_num == 0x19) { key = key19; } if (key) { - XeCryptHmacSha((void*)key, 0x10, inp_1, inp_1_size, inp_2, inp_2_size, - inp_3, inp_3_size, out, out_size); + XeCryptHmacSha_entry((void*)key, 0x10, inp_1, inp_1_size, inp_2, inp_2_size, + inp_3, inp_3_size, out, out_size); return X_STATUS_SUCCESS; } @@ -630,41 +633,42 @@ static const uint8_t xe_key_obfuscation_key[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -dword_result_t XeKeysAesCbcUsingKey(lpvoid_t obscured_key, lpvoid_t inp_ptr, - dword_t inp_size, lpvoid_t out_ptr, - lpvoid_t feed_ptr, dword_t encrypt) { +dword_result_t XeKeysAesCbcUsingKey_entry(lpvoid_t obscured_key, + lpvoid_t inp_ptr, dword_t inp_size, + lpvoid_t out_ptr, lpvoid_t feed_ptr, + dword_t encrypt) { uint8_t key[16]; // Deobscure key XECRYPT_AES_STATE aes; - XeCryptAesKey(&aes, (uint8_t*)xe_key_obfuscation_key); - XeCryptAesEcb(&aes, obscured_key, key, 0); + XeCryptAesKey_entry(&aes, (uint8_t*)xe_key_obfuscation_key); + XeCryptAesEcb_entry(&aes, obscured_key, key, 0); // Run CBC using deobscured key - XeCryptAesKey(&aes, key); - XeCryptAesCbc(&aes, inp_ptr, inp_size, out_ptr, feed_ptr, encrypt); + XeCryptAesKey_entry(&aes, key); + XeCryptAesCbc_entry(&aes, inp_ptr, inp_size, out_ptr, feed_ptr, encrypt); return X_STATUS_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(XeKeysAesCbcUsingKey, kNone, kImplemented); -dword_result_t XeKeysObscureKey(lpvoid_t input, lpvoid_t output) { +dword_result_t XeKeysObscureKey_entry(lpvoid_t input, lpvoid_t output) { // Based on HvxKeysObscureKey // Seems to encrypt input with per-console KEY_OBFUSCATION_KEY (key 0x18) XECRYPT_AES_STATE aes; - XeCryptAesKey(&aes, (uint8_t*)xe_key_obfuscation_key); - XeCryptAesEcb(&aes, input, output, 1); + XeCryptAesKey_entry(&aes, (uint8_t*)xe_key_obfuscation_key); + XeCryptAesEcb_entry(&aes, input, output, 1); return X_STATUS_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(XeKeysObscureKey, kNone, kImplemented); -dword_result_t XeKeysHmacShaUsingKey(lpvoid_t obscured_key, lpvoid_t inp_1, - dword_t inp_1_size, lpvoid_t inp_2, - dword_t inp_2_size, lpvoid_t inp_3, - dword_t inp_3_size, lpvoid_t out, - dword_t out_size) { +dword_result_t XeKeysHmacShaUsingKey_entry(lpvoid_t obscured_key, + lpvoid_t inp_1, dword_t inp_1_size, + lpvoid_t inp_2, dword_t inp_2_size, + lpvoid_t inp_3, dword_t inp_3_size, + lpvoid_t out, dword_t out_size) { if (!obscured_key) { return X_STATUS_INVALID_PARAMETER; } @@ -673,18 +677,17 @@ dword_result_t XeKeysHmacShaUsingKey(lpvoid_t obscured_key, lpvoid_t inp_1, // Deobscure key XECRYPT_AES_STATE aes; - XeCryptAesKey(&aes, (uint8_t*)xe_key_obfuscation_key); - XeCryptAesEcb(&aes, obscured_key, key, 0); + XeCryptAesKey_entry(&aes, (uint8_t*)xe_key_obfuscation_key); + XeCryptAesEcb_entry(&aes, obscured_key, key, 0); - XeCryptHmacSha(key, 0x10, inp_1, inp_1_size, inp_2, inp_2_size, inp_3, - inp_3_size, out, out_size); + XeCryptHmacSha_entry(key, 0x10, inp_1, inp_1_size, inp_2, inp_2_size, inp_3, + inp_3_size, out, out_size); return X_STATUS_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(XeKeysHmacShaUsingKey, kNone, kImplemented); -void RegisterCryptExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Crypt); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc index 5dd7b3309..0bc8a8f8d 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -19,7 +19,7 @@ namespace xe { namespace kernel { namespace xboxkrnl { -void DbgBreakPoint() { xe::debugging::Break(); } +void DbgBreakPoint_entry() { xe::debugging::Break(); } DECLARE_XBOXKRNL_EXPORT2(DbgBreakPoint, kDebug, kStub, kImportant); // https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx @@ -123,8 +123,8 @@ void HandleCppException(pointer_t record) { xe::debugging::Break(); } -void RtlRaiseException(pointer_t record) { - switch (record->exception_code) { +void RtlRaiseException_entry(pointer_t record) { + switch (record->code) { case 0x406D1388: { HandleSetThreadName(record); return; @@ -141,8 +141,8 @@ void RtlRaiseException(pointer_t record) { } DECLARE_XBOXKRNL_EXPORT2(RtlRaiseException, kDebug, kStub, kImportant); -void KeBugCheckEx(dword_t code, dword_t param1, dword_t param2, dword_t param3, - dword_t param4) { +void KeBugCheckEx_entry(dword_t code, dword_t param1, dword_t param2, + dword_t param3, dword_t param4) { XELOGD("*** STOP: 0x{:08X} (0x{:08X}, 0x{:08X}, 0x{:08X}, 0x{:08X})", code, param1, param2, param3, param4); fflush(stdout); @@ -151,12 +151,11 @@ void KeBugCheckEx(dword_t code, dword_t param1, dword_t param2, dword_t param3, } DECLARE_XBOXKRNL_EXPORT2(KeBugCheckEx, kDebug, kStub, kImportant); -void KeBugCheck(dword_t code) { KeBugCheckEx(code, 0, 0, 0, 0); } +void KeBugCheck_entry(dword_t code) { KeBugCheckEx_entry(code, 0, 0, 0, 0); } DECLARE_XBOXKRNL_EXPORT2(KeBugCheck, kDebug, kImplemented, kImportant); -void RegisterDebugExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Debug); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc index 3a27d490b..c3c9ddb11 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -1011,15 +1011,14 @@ uint32_t xeRtlNtStatusToDosError(uint32_t source_status) { return 317; // ERROR_MR_MID_NOT_FOUND } -dword_result_t RtlNtStatusToDosError(dword_t source_status) { +dword_result_t RtlNtStatusToDosError_entry(dword_t source_status) { return xeRtlNtStatusToDosError(source_status); } DECLARE_XBOXKRNL_EXPORT3(RtlNtStatusToDosError, kNone, kImportant, kHighFrequency, kLogResult); -void RegisterErrorExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Error); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc index 658cc0d24..b173fd304 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,7 +17,7 @@ namespace xe { namespace kernel { namespace xboxkrnl { -void HalReturnToFirmware(dword_t routine) { +void HalReturnToFirmware_entry(dword_t routine) { // void // IN FIRMWARE_REENTRY Routine @@ -31,9 +31,8 @@ void HalReturnToFirmware(dword_t routine) { } DECLARE_XBOXKRNL_EXPORT2(HalReturnToFirmware, kNone, kStub, kImportant); -void RegisterHalExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Hal); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_hid.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_hid.cc index 0ce308237..15e60161e 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_hid.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_hid.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,7 +17,7 @@ namespace xe { namespace kernel { namespace xboxkrnl { -dword_result_t HidReadKeys(dword_t unk1, unknown_t unk2, unknown_t unk3) { +dword_result_t HidReadKeys_entry(dword_t unk1, unknown_t unk2, unknown_t unk3) { /* TODO(gibbed): * Games check for the following errors: * 0xC000009D - translated to 0x48F - ERROR_DEVICE_NOT_CONNECTED @@ -32,9 +32,8 @@ dword_result_t HidReadKeys(dword_t unk1, unknown_t unk2, unknown_t unk3) { } DECLARE_XBOXKRNL_EXPORT1(HidReadKeys, kInput, kStub); -void RegisterHidExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Hid); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc index 37dc42aec..2e2022bc6 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -95,13 +95,13 @@ static bool IsValidPath(const std::string_view s, bool is_pattern) { return true; } -dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access, - pointer_t object_attrs, - pointer_t io_status_block, - lpqword_t allocation_size_ptr, - dword_t file_attributes, dword_t share_access, - dword_t creation_disposition, - dword_t create_options) { +dword_result_t NtCreateFile_entry(lpdword_t handle_out, dword_t desired_access, + pointer_t object_attrs, + pointer_t io_status_block, + lpqword_t allocation_size_ptr, + dword_t file_attributes, dword_t share_access, + dword_t creation_disposition, + dword_t create_options) { uint64_t allocation_size = 0; // is this correct??? if (allocation_size_ptr) { allocation_size = *allocation_size_ptr; @@ -170,22 +170,22 @@ dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access, } DECLARE_XBOXKRNL_EXPORT1(NtCreateFile, kFileSystem, kImplemented); -dword_result_t NtOpenFile(lpdword_t handle_out, dword_t desired_access, - pointer_t object_attributes, - pointer_t io_status_block, - dword_t open_options) { - return NtCreateFile(handle_out, desired_access, object_attributes, - io_status_block, nullptr, 0, 0, - static_cast(xe::vfs::FileDisposition::kOpen), - open_options); +dword_result_t NtOpenFile_entry( + lpdword_t handle_out, dword_t desired_access, + pointer_t object_attributes, + pointer_t io_status_block, dword_t open_options) { + return NtCreateFile_entry( + handle_out, desired_access, object_attributes, io_status_block, nullptr, + 0, 0, static_cast(xe::vfs::FileDisposition::kOpen), + open_options); } DECLARE_XBOXKRNL_EXPORT1(NtOpenFile, kFileSystem, kImplemented); -dword_result_t NtReadFile(dword_t file_handle, dword_t event_handle, - lpvoid_t apc_routine_ptr, lpvoid_t apc_context, - pointer_t io_status_block, - lpvoid_t buffer, dword_t buffer_length, - lpqword_t byte_offset_ptr) { +dword_result_t NtReadFile_entry(dword_t file_handle, dword_t event_handle, + lpvoid_t apc_routine_ptr, lpvoid_t apc_context, + pointer_t io_status_block, + lpvoid_t buffer, dword_t buffer_length, + lpqword_t byte_offset_ptr) { X_STATUS result = X_STATUS_SUCCESS; bool signal_event = false; @@ -265,11 +265,10 @@ dword_result_t NtReadFile(dword_t file_handle, dword_t event_handle, } DECLARE_XBOXKRNL_EXPORT2(NtReadFile, kFileSystem, kImplemented, kHighFrequency); -dword_result_t NtReadFileScatter(dword_t file_handle, dword_t event_handle, - lpvoid_t apc_routine_ptr, lpvoid_t apc_context, - pointer_t io_status_block, - lpdword_t segment_array, dword_t length, - lpqword_t byte_offset_ptr) { +dword_result_t NtReadFileScatter_entry( + dword_t file_handle, dword_t event_handle, lpvoid_t apc_routine_ptr, + lpvoid_t apc_context, pointer_t io_status_block, + lpdword_t segment_array, dword_t length, lpqword_t byte_offset_ptr) { X_STATUS result = X_STATUS_SUCCESS; bool signal_event = false; @@ -352,11 +351,11 @@ dword_result_t NtReadFileScatter(dword_t file_handle, dword_t event_handle, } DECLARE_XBOXKRNL_EXPORT1(NtReadFileScatter, kFileSystem, kImplemented); -dword_result_t NtWriteFile(dword_t file_handle, dword_t event_handle, - function_t apc_routine, lpvoid_t apc_context, - pointer_t io_status_block, - lpvoid_t buffer, dword_t buffer_length, - lpqword_t byte_offset_ptr) { +dword_result_t NtWriteFile_entry(dword_t file_handle, dword_t event_handle, + function_t apc_routine, lpvoid_t apc_context, + pointer_t io_status_block, + lpvoid_t buffer, dword_t buffer_length, + lpqword_t byte_offset_ptr) { X_STATUS result = X_STATUS_SUCCESS; // Grab event to signal. @@ -430,10 +429,10 @@ dword_result_t NtWriteFile(dword_t file_handle, dword_t event_handle, } DECLARE_XBOXKRNL_EXPORT1(NtWriteFile, kFileSystem, kImplemented); -dword_result_t NtCreateIoCompletion(lpdword_t out_handle, - dword_t desired_access, - lpvoid_t object_attribs, - dword_t num_concurrent_threads) { +dword_result_t NtCreateIoCompletion_entry(lpdword_t out_handle, + dword_t desired_access, + lpvoid_t object_attribs, + dword_t num_concurrent_threads) { auto completion = new XIOCompletion(kernel_state()); if (out_handle) { *out_handle = completion->handle(); @@ -443,9 +442,10 @@ dword_result_t NtCreateIoCompletion(lpdword_t out_handle, } DECLARE_XBOXKRNL_EXPORT1(NtCreateIoCompletion, kFileSystem, kImplemented); -dword_result_t NtSetIoCompletion(dword_t handle, dword_t key_context, - dword_t apc_context, dword_t completion_status, - dword_t num_bytes) { +dword_result_t NtSetIoCompletion_entry(dword_t handle, dword_t key_context, + dword_t apc_context, + dword_t completion_status, + dword_t num_bytes) { auto port = kernel_state()->object_table()->LookupObject(handle); if (!port) { @@ -465,7 +465,7 @@ DECLARE_XBOXKRNL_EXPORT2(NtSetIoCompletion, kFileSystem, kImplemented, kHighFrequency); // Dequeues a packet from the completion port. -dword_result_t NtRemoveIoCompletion( +dword_result_t NtRemoveIoCompletion_entry( dword_t handle, lpdword_t key_context, lpdword_t apc_context, pointer_t io_status_block, lpqword_t timeout) { X_STATUS status = X_STATUS_SUCCESS; @@ -502,7 +502,7 @@ dword_result_t NtRemoveIoCompletion( DECLARE_XBOXKRNL_EXPORT2(NtRemoveIoCompletion, kFileSystem, kImplemented, kHighFrequency); -dword_result_t NtQueryFullAttributesFile( +dword_result_t NtQueryFullAttributesFile_entry( pointer_t obj_attribs, pointer_t file_info) { auto object_name = @@ -544,7 +544,7 @@ dword_result_t NtQueryFullAttributesFile( } DECLARE_XBOXKRNL_EXPORT1(NtQueryFullAttributesFile, kFileSystem, kImplemented); -dword_result_t NtQueryDirectoryFile( +dword_result_t NtQueryDirectoryFile_entry( dword_t file_handle, dword_t event_handle, function_t apc_routine, lpvoid_t apc_context, pointer_t io_status_block, pointer_t file_info_ptr, dword_t length, @@ -588,7 +588,7 @@ dword_result_t NtQueryDirectoryFile( } DECLARE_XBOXKRNL_EXPORT1(NtQueryDirectoryFile, kFileSystem, kImplemented); -dword_result_t NtFlushBuffersFile( +dword_result_t NtFlushBuffersFile_entry( dword_t file_handle, pointer_t io_status_block_ptr) { auto result = X_STATUS_SUCCESS; @@ -602,7 +602,7 @@ dword_result_t NtFlushBuffersFile( DECLARE_XBOXKRNL_EXPORT1(NtFlushBuffersFile, kFileSystem, kStub); // https://docs.microsoft.com/en-us/windows/win32/devnotes/ntopensymboliclinkobject -dword_result_t NtOpenSymbolicLinkObject( +dword_result_t NtOpenSymbolicLinkObject_entry( lpdword_t handle_out, pointer_t object_attrs) { if (!object_attrs) { return X_STATUS_INVALID_PARAMETER; @@ -646,8 +646,8 @@ dword_result_t NtOpenSymbolicLinkObject( DECLARE_XBOXKRNL_EXPORT1(NtOpenSymbolicLinkObject, kFileSystem, kImplemented); // https://docs.microsoft.com/en-us/windows/win32/devnotes/ntquerysymboliclinkobject -dword_result_t NtQuerySymbolicLinkObject(dword_t handle, - pointer_t target) { +dword_result_t NtQuerySymbolicLinkObject_entry( + dword_t handle, pointer_t target) { auto symlink = kernel_state()->object_table()->LookupObject(handle); if (!symlink) { @@ -664,17 +664,17 @@ dword_result_t NtQuerySymbolicLinkObject(dword_t handle, } DECLARE_XBOXKRNL_EXPORT1(NtQuerySymbolicLinkObject, kFileSystem, kImplemented); -dword_result_t FscGetCacheElementCount(dword_t r3) { return 0; } +dword_result_t FscGetCacheElementCount_entry(dword_t r3) { return 0; } DECLARE_XBOXKRNL_EXPORT1(FscGetCacheElementCount, kFileSystem, kStub); -dword_result_t FscSetCacheElementCount(dword_t unk_0, dword_t unk_1) { +dword_result_t FscSetCacheElementCount_entry(dword_t unk_0, dword_t unk_1) { // unk_0 = 0 // unk_1 looks like a count? in what units? 256 is a common value return X_STATUS_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(FscSetCacheElementCount, kFileSystem, kStub); -dword_result_t NtDeviceIoControlFile( +dword_result_t NtDeviceIoControlFile_entry( dword_t handle, dword_t event_handle, dword_t apc_routine, dword_t apc_context, dword_t io_status_block, dword_t io_control_code, lpvoid_t input_buffer, dword_t input_buffer_len, lpvoid_t output_buffer, @@ -712,8 +712,9 @@ dword_result_t NtDeviceIoControlFile( } DECLARE_XBOXKRNL_EXPORT1(NtDeviceIoControlFile, kFileSystem, kStub); -dword_result_t IoCreateDevice(dword_t device_struct, dword_t r4, dword_t r5, - dword_t r6, dword_t r7, lpdword_t out_struct) { +dword_result_t IoCreateDevice_entry(dword_t device_struct, dword_t r4, + dword_t r5, dword_t r6, dword_t r7, + lpdword_t out_struct) { // Called from XMountUtilityDrive XAM-task code // That code tries writing things to a pointer at out_struct+0x18 // We'll alloc some scratch space for it so it doesn't cause any exceptions @@ -734,9 +735,8 @@ dword_result_t IoCreateDevice(dword_t device_struct, dword_t r4, dword_t r5, } DECLARE_XBOXKRNL_EXPORT1(IoCreateDevice, kFileSystem, kStub); -void RegisterIoExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Io); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc index e43db31e6..1ace11c97 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_io_info.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -54,7 +54,7 @@ uint32_t GetQueryFileInfoMinimumLength(uint32_t info_class) { } } -dword_result_t NtQueryInformationFile( +dword_result_t NtQueryInformationFile_entry( dword_t file_handle, pointer_t io_status_block_ptr, lpvoid_t info_ptr, dword_t info_length, dword_t info_class) { uint32_t minimum_length = GetQueryFileInfoMinimumLength(info_class); @@ -179,7 +179,7 @@ uint32_t GetSetFileInfoMinimumLength(uint32_t info_class) { } } -dword_result_t NtSetInformationFile( +dword_result_t NtSetInformationFile_entry( dword_t file_handle, pointer_t io_status_block, lpvoid_t info_ptr, dword_t info_length, dword_t info_class) { uint32_t minimum_length = GetSetFileInfoMinimumLength(info_class); @@ -277,7 +277,7 @@ uint32_t GetQueryVolumeInfoMinimumLength(uint32_t info_class) { } } -dword_result_t NtQueryVolumeInformationFile( +dword_result_t NtQueryVolumeInformationFile_entry( dword_t file_handle, pointer_t io_status_block_ptr, lpvoid_t info_ptr, dword_t info_length, dword_t info_class) { uint32_t minimum_length = GetQueryVolumeInfoMinimumLength(info_class); @@ -357,9 +357,8 @@ dword_result_t NtQueryVolumeInformationFile( DECLARE_XBOXKRNL_EXPORT1(NtQueryVolumeInformationFile, kFileSystem, kImplemented); -void RegisterIoInfoExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(IoInfo); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc index d53539286..7d72b3215 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -57,10 +57,11 @@ uint32_t FromXdkProtectFlags(uint32_t protect) { return result; } -dword_result_t NtAllocateVirtualMemory(lpdword_t base_addr_ptr, - lpdword_t region_size_ptr, - dword_t alloc_type, dword_t protect_bits, - dword_t debug_memory) { +dword_result_t NtAllocateVirtualMemory_entry(lpdword_t base_addr_ptr, + lpdword_t region_size_ptr, + dword_t alloc_type, + dword_t protect_bits, + dword_t debug_memory) { // NTSTATUS // _Inout_ PVOID *BaseAddress, // _Inout_ PSIZE_T RegionSize, @@ -189,11 +190,11 @@ dword_result_t NtAllocateVirtualMemory(lpdword_t base_addr_ptr, } DECLARE_XBOXKRNL_EXPORT1(NtAllocateVirtualMemory, kMemory, kImplemented); -dword_result_t NtProtectVirtualMemory(lpdword_t base_addr_ptr, - lpdword_t region_size_ptr, - dword_t protect_bits, - lpdword_t old_protect, - dword_t debug_memory) { +dword_result_t NtProtectVirtualMemory_entry(lpdword_t base_addr_ptr, + lpdword_t region_size_ptr, + dword_t protect_bits, + lpdword_t old_protect, + dword_t debug_memory) { // Set to TRUE when this memory refers to devkit memory area. assert_true(debug_memory == 0); @@ -239,9 +240,10 @@ dword_result_t NtProtectVirtualMemory(lpdword_t base_addr_ptr, } DECLARE_XBOXKRNL_EXPORT1(NtProtectVirtualMemory, kMemory, kImplemented); -dword_result_t NtFreeVirtualMemory(lpdword_t base_addr_ptr, - lpdword_t region_size_ptr, dword_t free_type, - dword_t debug_memory) { +dword_result_t NtFreeVirtualMemory_entry(lpdword_t base_addr_ptr, + lpdword_t region_size_ptr, + dword_t free_type, + dword_t debug_memory) { uint32_t base_addr_value = *base_addr_ptr; uint32_t region_size_value = *region_size_ptr; // X_MEM_DECOMMIT | X_MEM_RELEASE @@ -293,7 +295,7 @@ struct X_MEMORY_BASIC_INFORMATION { be type; }; -dword_result_t NtQueryVirtualMemory( +dword_result_t NtQueryVirtualMemory_entry( dword_t base_address, pointer_t memory_basic_information_ptr) { auto heap = kernel_state()->memory()->LookupHeap(base_address); @@ -328,11 +330,9 @@ dword_result_t NtQueryVirtualMemory( } DECLARE_XBOXKRNL_EXPORT1(NtQueryVirtualMemory, kMemory, kImplemented); -dword_result_t MmAllocatePhysicalMemoryEx(dword_t flags, dword_t region_size, - dword_t protect_bits, - dword_t min_addr_range, - dword_t max_addr_range, - dword_t alignment) { +dword_result_t MmAllocatePhysicalMemoryEx_entry( + dword_t flags, dword_t region_size, dword_t protect_bits, + dword_t min_addr_range, dword_t max_addr_range, dword_t alignment) { // Type will usually be 0 (user request?), where 1 and 2 are sometimes made // by D3D/etc. @@ -392,14 +392,15 @@ dword_result_t MmAllocatePhysicalMemoryEx(dword_t flags, dword_t region_size, } DECLARE_XBOXKRNL_EXPORT1(MmAllocatePhysicalMemoryEx, kMemory, kImplemented); -dword_result_t MmAllocatePhysicalMemory(dword_t flags, dword_t region_size, - dword_t protect_bits) { - return MmAllocatePhysicalMemoryEx(flags, region_size, protect_bits, 0, - 0xFFFFFFFFu, 0); +dword_result_t MmAllocatePhysicalMemory_entry(dword_t flags, + dword_t region_size, + dword_t protect_bits) { + return MmAllocatePhysicalMemoryEx_entry(flags, region_size, protect_bits, 0, + 0xFFFFFFFFu, 0); } DECLARE_XBOXKRNL_EXPORT1(MmAllocatePhysicalMemory, kMemory, kImplemented); -void MmFreePhysicalMemory(dword_t type, dword_t base_address) { +void MmFreePhysicalMemory_entry(dword_t type, dword_t base_address) { // base_address = result of MmAllocatePhysicalMemory. assert_true((base_address & 0x1F) == 0); @@ -409,7 +410,7 @@ void MmFreePhysicalMemory(dword_t type, dword_t base_address) { } DECLARE_XBOXKRNL_EXPORT1(MmFreePhysicalMemory, kMemory, kImplemented); -dword_result_t MmQueryAddressProtect(dword_t base_address) { +dword_result_t MmQueryAddressProtect_entry(dword_t base_address) { auto heap = kernel_state()->memory()->LookupHeap(base_address); uint32_t access; if (!heap->QueryProtect(base_address, &access)) { @@ -422,8 +423,8 @@ dword_result_t MmQueryAddressProtect(dword_t base_address) { DECLARE_XBOXKRNL_EXPORT2(MmQueryAddressProtect, kMemory, kImplemented, kHighFrequency); -void MmSetAddressProtect(lpvoid_t base_address, dword_t region_size, - dword_t protect_bits) { +void MmSetAddressProtect_entry(lpvoid_t base_address, dword_t region_size, + dword_t protect_bits) { if (!protect_bits) { XELOGE("MmSetAddressProtect: Failed due to incorrect protect_bits"); return; @@ -435,7 +436,7 @@ void MmSetAddressProtect(lpvoid_t base_address, dword_t region_size, } DECLARE_XBOXKRNL_EXPORT1(MmSetAddressProtect, kMemory, kImplemented); -dword_result_t MmQueryAllocationSize(lpvoid_t base_address) { +dword_result_t MmQueryAllocationSize_entry(lpvoid_t base_address) { auto heap = kernel_state()->memory()->LookupHeap(base_address); uint32_t size; if (!heap->QuerySize(base_address, &size)) { @@ -471,7 +472,7 @@ struct X_MM_QUERY_STATISTICS_RESULT { }; static_assert_size(X_MM_QUERY_STATISTICS_RESULT, 104); -dword_result_t MmQueryStatistics( +dword_result_t MmQueryStatistics_entry( pointer_t stats_ptr) { if (!stats_ptr) { return X_STATUS_INVALID_PARAMETER; @@ -550,7 +551,7 @@ dword_result_t MmQueryStatistics( DECLARE_XBOXKRNL_EXPORT1(MmQueryStatistics, kMemory, kImplemented); // https://msdn.microsoft.com/en-us/library/windows/hardware/ff554547(v=vs.85).aspx -dword_result_t MmGetPhysicalAddress(dword_t base_address) { +dword_result_t MmGetPhysicalAddress_entry(dword_t base_address) { // PHYSICAL_ADDRESS MmGetPhysicalAddress( // _In_ PVOID BaseAddress // ); @@ -564,8 +565,8 @@ dword_result_t MmGetPhysicalAddress(dword_t base_address) { } DECLARE_XBOXKRNL_EXPORT1(MmGetPhysicalAddress, kMemory, kImplemented); -dword_result_t MmMapIoSpace(dword_t unk0, lpvoid_t src_address, dword_t size, - dword_t flags) { +dword_result_t MmMapIoSpace_entry(dword_t unk0, lpvoid_t src_address, + dword_t size, dword_t flags) { // I've only seen this used to map XMA audio contexts. // The code seems fine with taking the src address, so this just returns that. // If others start using it there could be problems. @@ -577,8 +578,8 @@ dword_result_t MmMapIoSpace(dword_t unk0, lpvoid_t src_address, dword_t size, } DECLARE_XBOXKRNL_EXPORT1(MmMapIoSpace, kMemory, kImplemented); -dword_result_t ExAllocatePoolTypeWithTag(dword_t size, dword_t tag, - dword_t zero) { +dword_result_t ExAllocatePoolTypeWithTag_entry(dword_t size, dword_t tag, + dword_t zero) { uint32_t alignment = 8; uint32_t adjusted_size = size; if (adjusted_size < 4 * 1024) { @@ -594,33 +595,33 @@ dword_result_t ExAllocatePoolTypeWithTag(dword_t size, dword_t tag, } DECLARE_XBOXKRNL_EXPORT1(ExAllocatePoolTypeWithTag, kMemory, kImplemented); -dword_result_t ExAllocatePool(dword_t size) { +dword_result_t ExAllocatePool_entry(dword_t size) { const uint32_t none = 0x656E6F4E; // 'None' - return ExAllocatePoolTypeWithTag(size, none, 0); + return ExAllocatePoolTypeWithTag_entry(size, none, 0); } DECLARE_XBOXKRNL_EXPORT1(ExAllocatePool, kMemory, kImplemented); -void ExFreePool(lpvoid_t base_address) { +void ExFreePool_entry(lpvoid_t base_address) { kernel_state()->memory()->SystemHeapFree(base_address); } DECLARE_XBOXKRNL_EXPORT1(ExFreePool, kMemory, kImplemented); -dword_result_t KeGetImagePageTableEntry(lpvoid_t address) { +dword_result_t KeGetImagePageTableEntry_entry(lpvoid_t address) { // Unknown return 1; } DECLARE_XBOXKRNL_EXPORT1(KeGetImagePageTableEntry, kMemory, kStub); -dword_result_t KeLockL2() { +dword_result_t KeLockL2_entry() { // TODO return 0; } DECLARE_XBOXKRNL_EXPORT1(KeLockL2, kMemory, kStub); -void KeUnlockL2() {} +void KeUnlockL2_entry() {} DECLARE_XBOXKRNL_EXPORT1(KeUnlockL2, kMemory, kStub); -dword_result_t MmCreateKernelStack(dword_t stack_size, dword_t r4) { +dword_result_t MmCreateKernelStack_entry(dword_t stack_size, dword_t r4) { assert_zero(r4); // Unknown argument. auto stack_size_aligned = (stack_size + 0xFFF) & 0xFFFFF000; @@ -637,7 +638,8 @@ dword_result_t MmCreateKernelStack(dword_t stack_size, dword_t r4) { } DECLARE_XBOXKRNL_EXPORT1(MmCreateKernelStack, kMemory, kImplemented); -dword_result_t MmDeleteKernelStack(lpvoid_t stack_base, lpvoid_t stack_end) { +dword_result_t MmDeleteKernelStack_entry(lpvoid_t stack_base, + lpvoid_t stack_end) { // Release the stack (where stack_end is the low address) if (kernel_memory()->LookupHeap(0x70000000)->Release(stack_end)) { return X_STATUS_SUCCESS; @@ -647,9 +649,8 @@ dword_result_t MmDeleteKernelStack(lpvoid_t stack_base, lpvoid_t stack_end) { } DECLARE_XBOXKRNL_EXPORT1(MmDeleteKernelStack, kMemory, kImplemented); -void RegisterMemoryExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel -} // namespace xe \ No newline at end of file +} // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Memory); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc index 834b5102f..7a100665a 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,14 +18,13 @@ namespace xe { namespace kernel { namespace xboxkrnl { -void KeEnableFpuExceptions(dword_t enabled) { +void KeEnableFpuExceptions_entry(dword_t enabled) { // TODO(benvanik): can we do anything about exceptions? } DECLARE_XBOXKRNL_EXPORT1(KeEnableFpuExceptions, kNone, kStub); -void RegisterMiscExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Misc); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc index f6b9846e0..f70f30bd0 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc @@ -83,25 +83,10 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) RegisterExportTable(export_resolver_); // Register all exported functions. - RegisterAudioExports(export_resolver_, kernel_state_); - RegisterAudioXmaExports(export_resolver_, kernel_state_); - RegisterCryptExports(export_resolver_, kernel_state_); - RegisterDebugExports(export_resolver_, kernel_state_); - RegisterErrorExports(export_resolver_, kernel_state_); - RegisterHalExports(export_resolver_, kernel_state_); - RegisterHidExports(export_resolver_, kernel_state_); - RegisterIoExports(export_resolver_, kernel_state_); - RegisterIoInfoExports(export_resolver_, kernel_state_); - RegisterMemoryExports(export_resolver_, kernel_state_); - RegisterMiscExports(export_resolver_, kernel_state_); - RegisterModuleExports(export_resolver_, kernel_state_); - RegisterObExports(export_resolver_, kernel_state_); - RegisterRtlExports(export_resolver_, kernel_state_); - RegisterStringExports(export_resolver_, kernel_state_); - RegisterThreadingExports(export_resolver_, kernel_state_); - RegisterUsbcamExports(export_resolver_, kernel_state_); - RegisterVideoExports(export_resolver_, kernel_state_); - RegisterXConfigExports(export_resolver_, kernel_state_); +#define XE_MODULE_EXPORT_GROUP(m, n) \ + Register##n##Exports(export_resolver_, kernel_state_); +#include "xboxkrnl_module_export_groups.inc" +#undef XE_MODULE_EXPORT_GROUP // KeDebugMonitorData (?*) // Set to a valid value when a remote debugger is attached. diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_module_export_groups.inc b/src/xenia/kernel/xboxkrnl/xboxkrnl_module_export_groups.inc new file mode 100644 index 000000000..2506c9004 --- /dev/null +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_module_export_groups.inc @@ -0,0 +1,31 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +// This is a partial file designed to be included by other files when +// constructing various tables. + +XE_MODULE_EXPORT_GROUP(xboxkrnl, Audio) +XE_MODULE_EXPORT_GROUP(xboxkrnl, AudioXma) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Crypt) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Debug) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Error) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Hal) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Hid) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Io) +XE_MODULE_EXPORT_GROUP(xboxkrnl, IoInfo) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Memory) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Misc) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Module) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Ob) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Rtl) +XE_MODULE_EXPORT_GROUP(xboxkrnl, String) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Threading) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Usbcam) +XE_MODULE_EXPORT_GROUP(xboxkrnl, Video) +XE_MODULE_EXPORT_GROUP(xboxkrnl, XConfig) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc index 41f4b5d54..b17e4b2a2 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_modules.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -19,7 +19,7 @@ namespace xe { namespace kernel { namespace xboxkrnl { -dword_result_t XexCheckExecutablePrivilege(dword_t privilege) { +dword_result_t XexCheckExecutablePrivilege_entry(dword_t privilege) { // BOOL // DWORD Privilege @@ -39,8 +39,8 @@ dword_result_t XexCheckExecutablePrivilege(dword_t privilege) { } DECLARE_XBOXKRNL_EXPORT1(XexCheckExecutablePrivilege, kModules, kImplemented); -dword_result_t XexGetModuleHandle(lpstring_t module_name, - lpdword_t hmodule_ptr) { +dword_result_t XexGetModuleHandle_entry(lpstring_t module_name, + lpdword_t hmodule_ptr) { object_ref module; if (!module_name) { @@ -61,8 +61,9 @@ dword_result_t XexGetModuleHandle(lpstring_t module_name, } DECLARE_XBOXKRNL_EXPORT1(XexGetModuleHandle, kModules, kImplemented); -dword_result_t XexGetModuleSection(lpvoid_t hmodule, lpstring_t name, - lpdword_t data_ptr, lpdword_t size_ptr) { +dword_result_t XexGetModuleSection_entry(lpvoid_t hmodule, lpstring_t name, + lpdword_t data_ptr, + lpdword_t size_ptr) { X_STATUS result = X_STATUS_SUCCESS; auto module = XModule::GetFromHModule(kernel_state(), hmodule); @@ -82,8 +83,8 @@ dword_result_t XexGetModuleSection(lpvoid_t hmodule, lpstring_t name, } DECLARE_XBOXKRNL_EXPORT1(XexGetModuleSection, kModules, kImplemented); -dword_result_t XexLoadImage(lpstring_t module_name, dword_t module_flags, - dword_t min_version, lpdword_t hmodule_ptr) { +dword_result_t XexLoadImage_entry(lpstring_t module_name, dword_t module_flags, + dword_t min_version, lpdword_t hmodule_ptr) { X_STATUS result = X_STATUS_NO_SUCH_FILE; uint32_t hmodule = 0; @@ -117,7 +118,7 @@ dword_result_t XexLoadImage(lpstring_t module_name, dword_t module_flags, } DECLARE_XBOXKRNL_EXPORT1(XexLoadImage, kModules, kImplemented); -dword_result_t XexUnloadImage(lpvoid_t hmodule) { +dword_result_t XexUnloadImage_entry(lpvoid_t hmodule) { auto module = XModule::GetFromHModule(kernel_state(), hmodule); if (!module) { return X_STATUS_INVALID_HANDLE; @@ -138,8 +139,8 @@ dword_result_t XexUnloadImage(lpvoid_t hmodule) { } DECLARE_XBOXKRNL_EXPORT1(XexUnloadImage, kModules, kImplemented); -dword_result_t XexGetProcedureAddress(lpvoid_t hmodule, dword_t ordinal, - lpdword_t out_function_ptr) { +dword_result_t XexGetProcedureAddress_entry(lpvoid_t hmodule, dword_t ordinal, + lpdword_t out_function_ptr) { // May be entry point? assert_not_zero(ordinal); @@ -166,7 +167,15 @@ dword_result_t XexGetProcedureAddress(lpvoid_t hmodule, dword_t ordinal, *out_function_ptr = ptr; result = X_STATUS_SUCCESS; } else { - XELOGW("ERROR: XexGetProcedureAddress ordinal not found!"); + if (is_string_name) { + XELOGW("ERROR: XexGetProcedureAddress export '{}' in '{}' not found!", + string_name, module->name()); + } else { + XELOGW( + "ERROR: XexGetProcedureAddress ordinal {} (0x{:X}) in '{}' not " + "found!", + ordinal, ordinal, module->name()); + } *out_function_ptr = 0; result = X_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND; } @@ -176,7 +185,7 @@ dword_result_t XexGetProcedureAddress(lpvoid_t hmodule, dword_t ordinal, } DECLARE_XBOXKRNL_EXPORT1(XexGetProcedureAddress, kModules, kImplemented); -void ExRegisterTitleTerminateNotification( +void ExRegisterTitleTerminateNotification_entry( pointer_t reg, dword_t create) { if (create) { // Adding. @@ -190,9 +199,8 @@ void ExRegisterTitleTerminateNotification( DECLARE_XBOXKRNL_EXPORT1(ExRegisterTitleTerminateNotification, kModules, kImplemented); -void RegisterModuleExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Module); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc index 68564a055..1eec0e430 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_ob.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -20,9 +20,9 @@ namespace xe { namespace kernel { namespace xboxkrnl { -dword_result_t ObOpenObjectByName(lpunknown_t obj_attributes_ptr, - lpunknown_t object_type_ptr, dword_t unk, - lpdword_t handle_ptr) { +dword_result_t ObOpenObjectByName_entry(lpunknown_t obj_attributes_ptr, + lpunknown_t object_type_ptr, + dword_t unk, lpdword_t handle_ptr) { // r3 = ptr to info? // +0 = -4 // +4 = name ptr @@ -47,8 +47,8 @@ dword_result_t ObOpenObjectByName(lpunknown_t obj_attributes_ptr, } DECLARE_XBOXKRNL_EXPORT1(ObOpenObjectByName, kNone, kImplemented); -dword_result_t ObOpenObjectByPointer(lpvoid_t object_ptr, - lpdword_t out_handle_ptr) { +dword_result_t ObOpenObjectByPointer_entry(lpvoid_t object_ptr, + lpdword_t out_handle_ptr) { auto object = XObject::GetNativeObject(kernel_state(), object_ptr); if (!object) { return X_STATUS_UNSUCCESSFUL; @@ -61,8 +61,8 @@ dword_result_t ObOpenObjectByPointer(lpvoid_t object_ptr, } DECLARE_XBOXKRNL_EXPORT1(ObOpenObjectByPointer, kNone, kImplemented); -dword_result_t ObLookupThreadByThreadId(dword_t thread_id, - lpdword_t out_object_ptr) { +dword_result_t ObLookupThreadByThreadId_entry(dword_t thread_id, + lpdword_t out_object_ptr) { auto thread = kernel_state()->GetThreadByID(thread_id); if (!thread) { return X_STATUS_NOT_FOUND; @@ -75,9 +75,9 @@ dword_result_t ObLookupThreadByThreadId(dword_t thread_id, } DECLARE_XBOXKRNL_EXPORT1(ObLookupThreadByThreadId, kNone, kImplemented); -dword_result_t ObReferenceObjectByHandle(dword_t handle, - dword_t object_type_ptr, - lpdword_t out_object_ptr) { +dword_result_t ObReferenceObjectByHandle_entry(dword_t handle, + dword_t object_type_ptr, + lpdword_t out_object_ptr) { // These values come from how Xenia handles uninitialized kernel data exports. // D###BEEF where ### is the ordinal. const static std::unordered_map object_types = { @@ -109,22 +109,24 @@ dword_result_t ObReferenceObjectByHandle(dword_t handle, } DECLARE_XBOXKRNL_EXPORT1(ObReferenceObjectByHandle, kNone, kImplemented); -dword_result_t ObReferenceObjectByName(lpstring_t name, dword_t attributes, - dword_t object_type_ptr, - lpvoid_t parse_context, - lpdword_t out_object_ptr) { +dword_result_t ObReferenceObjectByName_entry(lpstring_t name, + dword_t attributes, + dword_t object_type_ptr, + lpvoid_t parse_context, + lpdword_t out_object_ptr) { X_HANDLE handle = X_INVALID_HANDLE_VALUE; X_STATUS result = kernel_state()->object_table()->GetObjectByName(name.value(), &handle); if (XSUCCEEDED(result)) { - return ObReferenceObjectByHandle(handle, object_type_ptr, out_object_ptr); + return ObReferenceObjectByHandle_entry(handle, object_type_ptr, + out_object_ptr); } return result; } DECLARE_XBOXKRNL_EXPORT1(ObReferenceObjectByName, kNone, kImplemented); -dword_result_t ObDereferenceObject(dword_t native_ptr) { +dword_result_t ObDereferenceObject_entry(dword_t native_ptr) { // Check if a dummy value from ObReferenceObjectByHandle. if (native_ptr == 0xDEADF00D) { return 0; @@ -140,8 +142,8 @@ dword_result_t ObDereferenceObject(dword_t native_ptr) { } DECLARE_XBOXKRNL_EXPORT1(ObDereferenceObject, kNone, kImplemented); -dword_result_t ObCreateSymbolicLink(pointer_t path_ptr, - pointer_t target_ptr) { +dword_result_t ObCreateSymbolicLink_entry(pointer_t path_ptr, + pointer_t target_ptr) { auto path = util::TranslateAnsiString(kernel_memory(), path_ptr); auto target = util::TranslateAnsiString(kernel_memory(), target_ptr); path = xe::utf8::canonicalize_guest_path(path); @@ -159,7 +161,7 @@ dword_result_t ObCreateSymbolicLink(pointer_t path_ptr, } DECLARE_XBOXKRNL_EXPORT1(ObCreateSymbolicLink, kNone, kImplemented); -dword_result_t ObDeleteSymbolicLink(pointer_t path_ptr) { +dword_result_t ObDeleteSymbolicLink_entry(pointer_t path_ptr) { auto path = util::TranslateAnsiString(kernel_memory(), path_ptr); if (!kernel_state()->file_system()->UnregisterSymbolicLink(path)) { return X_STATUS_UNSUCCESSFUL; @@ -169,8 +171,8 @@ dword_result_t ObDeleteSymbolicLink(pointer_t path_ptr) { } DECLARE_XBOXKRNL_EXPORT1(ObDeleteSymbolicLink, kNone, kImplemented); -dword_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr, - dword_t options) { +dword_result_t NtDuplicateObject_entry(dword_t handle, lpdword_t new_handle_ptr, + dword_t options) { // NOTE: new_handle_ptr can be zero to just close a handle. // NOTE: this function seems to be used to get the current thread handle // (passed handle=-2). @@ -194,14 +196,13 @@ dword_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr, } DECLARE_XBOXKRNL_EXPORT1(NtDuplicateObject, kNone, kImplemented); -dword_result_t NtClose(dword_t handle) { +dword_result_t NtClose_entry(dword_t handle) { return kernel_state()->object_table()->ReleaseHandle(handle); } DECLARE_XBOXKRNL_EXPORT1(NtClose, kNone, kImplemented); -void RegisterObExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Ob); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_private.h b/src/xenia/kernel/xboxkrnl/xboxkrnl_private.h index d1f081518..379577176 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_private.h +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_private.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -21,29 +21,11 @@ namespace xboxkrnl { xe::cpu::Export* RegisterExport_xboxkrnl(xe::cpu::Export* export_entry); // Registration functions, one per file. -#define DECLARE_REGISTER_EXPORTS(n) \ +#define XE_MODULE_EXPORT_GROUP(m, n) \ void Register##n##Exports(xe::cpu::ExportResolver* export_resolver, \ - KernelState* kernel_state) -DECLARE_REGISTER_EXPORTS(Audio); -DECLARE_REGISTER_EXPORTS(AudioXma); -DECLARE_REGISTER_EXPORTS(Crypt); -DECLARE_REGISTER_EXPORTS(Debug); -DECLARE_REGISTER_EXPORTS(Error); -DECLARE_REGISTER_EXPORTS(Hal); -DECLARE_REGISTER_EXPORTS(Hid); -DECLARE_REGISTER_EXPORTS(Io); -DECLARE_REGISTER_EXPORTS(IoInfo); -DECLARE_REGISTER_EXPORTS(Memory); -DECLARE_REGISTER_EXPORTS(Misc); -DECLARE_REGISTER_EXPORTS(Module); -DECLARE_REGISTER_EXPORTS(Ob); -DECLARE_REGISTER_EXPORTS(Rtl); -DECLARE_REGISTER_EXPORTS(String); -DECLARE_REGISTER_EXPORTS(Threading); -DECLARE_REGISTER_EXPORTS(Usbcam); -DECLARE_REGISTER_EXPORTS(Video); -DECLARE_REGISTER_EXPORTS(XConfig); -#undef DECLARE_REGISTER_EXPORTS + KernelState* kernel_state); +#include "xboxkrnl_module_export_groups.inc" +#undef XE_MODULE_EXPORT_GROUP } // namespace xboxkrnl } // namespace kernel diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc index db3cef5db..adb07c81b 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -30,8 +30,8 @@ namespace kernel { namespace xboxkrnl { // https://msdn.microsoft.com/en-us/library/ff561778 -dword_result_t RtlCompareMemory(lpvoid_t source1, lpvoid_t source2, - dword_t length) { +dword_result_t RtlCompareMemory_entry(lpvoid_t source1, lpvoid_t source2, + dword_t length) { uint8_t* p1 = source1; uint8_t* p2 = source2; @@ -51,8 +51,8 @@ dword_result_t RtlCompareMemory(lpvoid_t source1, lpvoid_t source2, DECLARE_XBOXKRNL_EXPORT1(RtlCompareMemory, kMemory, kImplemented); // https://msdn.microsoft.com/en-us/library/ff552123 -dword_result_t RtlCompareMemoryUlong(lpvoid_t source, dword_t length, - dword_t pattern) { +dword_result_t RtlCompareMemoryUlong_entry(lpvoid_t source, dword_t length, + dword_t pattern) { // Return 0 if source/length not aligned if (source.guest_address() % 4 || length % 4) { return 0; @@ -72,7 +72,8 @@ dword_result_t RtlCompareMemoryUlong(lpvoid_t source, dword_t length, DECLARE_XBOXKRNL_EXPORT1(RtlCompareMemoryUlong, kMemory, kImplemented); // https://msdn.microsoft.com/en-us/library/ff552263 -void RtlFillMemoryUlong(lpvoid_t destination, dword_t length, dword_t pattern) { +void RtlFillMemoryUlong_entry(lpvoid_t destination, dword_t length, + dword_t pattern) { // NOTE: length must be % 4, so we can work on uint32s. uint32_t count = length >> 2; @@ -84,7 +85,7 @@ void RtlFillMemoryUlong(lpvoid_t destination, dword_t length, dword_t pattern) { } DECLARE_XBOXKRNL_EXPORT1(RtlFillMemoryUlong, kMemory, kImplemented); -dword_result_t RtlUpperChar(dword_t in) { +dword_result_t RtlUpperChar_entry(dword_t in) { char c = in & 0xFF; if (c >= 'a' && c <= 'z') { return c ^ 0x20; @@ -94,7 +95,7 @@ dword_result_t RtlUpperChar(dword_t in) { } DECLARE_XBOXKRNL_EXPORT1(RtlUpperChar, kNone, kImplemented); -dword_result_t RtlLowerChar(dword_t in) { +dword_result_t RtlLowerChar_entry(dword_t in) { char c = in & 0xFF; if (c >= 'A' && c <= 'Z') { return c ^ 0x20; @@ -104,8 +105,8 @@ dword_result_t RtlLowerChar(dword_t in) { } DECLARE_XBOXKRNL_EXPORT1(RtlLowerChar, kNone, kImplemented); -dword_result_t RtlCompareString(lpstring_t string_1, lpstring_t string_2, - dword_t case_insensitive) { +dword_result_t RtlCompareString_entry(lpstring_t string_1, lpstring_t string_2, + dword_t case_insensitive) { int ret = case_insensitive ? strcasecmp(string_1, string_2) : std::strcmp(string_1, string_2); @@ -113,9 +114,11 @@ dword_result_t RtlCompareString(lpstring_t string_1, lpstring_t string_2, } DECLARE_XBOXKRNL_EXPORT1(RtlCompareString, kNone, kImplemented); -dword_result_t RtlCompareStringN(lpstring_t string_1, dword_t string_1_len, - lpstring_t string_2, dword_t string_2_len, - dword_t case_insensitive) { +dword_result_t RtlCompareStringN_entry(lpstring_t string_1, + dword_t string_1_len, + lpstring_t string_2, + dword_t string_2_len, + dword_t case_insensitive) { uint32_t len1 = string_1_len; uint32_t len2 = string_2_len; @@ -135,8 +138,8 @@ dword_result_t RtlCompareStringN(lpstring_t string_1, dword_t string_1_len, DECLARE_XBOXKRNL_EXPORT1(RtlCompareStringN, kNone, kImplemented); // https://msdn.microsoft.com/en-us/library/ff561918 -void RtlInitAnsiString(pointer_t destination, - lpstring_t source) { +void RtlInitAnsiString_entry(pointer_t destination, + lpstring_t source) { if (source) { uint16_t length = (uint16_t)strlen(source); destination->length = length; @@ -150,7 +153,7 @@ void RtlInitAnsiString(pointer_t destination, DECLARE_XBOXKRNL_EXPORT1(RtlInitAnsiString, kNone, kImplemented); // https://msdn.microsoft.com/en-us/library/ff561899 -void RtlFreeAnsiString(pointer_t string) { +void RtlFreeAnsiString_entry(pointer_t string) { if (string->pointer) { kernel_memory()->SystemHeapFree(string->pointer); } @@ -160,8 +163,8 @@ void RtlFreeAnsiString(pointer_t string) { DECLARE_XBOXKRNL_EXPORT1(RtlFreeAnsiString, kNone, kImplemented); // https://msdn.microsoft.com/en-us/library/ff561934 -void RtlInitUnicodeString(pointer_t destination, - lpu16string_t source) { +void RtlInitUnicodeString_entry(pointer_t destination, + lpu16string_t source) { if (source) { destination->length = (uint16_t)source.value().size() * 2; destination->maximum_length = (uint16_t)(source.value().size() + 1) * 2; @@ -173,7 +176,7 @@ void RtlInitUnicodeString(pointer_t destination, DECLARE_XBOXKRNL_EXPORT1(RtlInitUnicodeString, kNone, kImplemented); // https://msdn.microsoft.com/en-us/library/ff561903 -void RtlFreeUnicodeString(pointer_t string) { +void RtlFreeUnicodeString_entry(pointer_t string) { if (string->pointer) { kernel_memory()->SystemHeapFree(string->pointer); } @@ -182,8 +185,8 @@ void RtlFreeUnicodeString(pointer_t string) { } DECLARE_XBOXKRNL_EXPORT1(RtlFreeUnicodeString, kNone, kImplemented); -void RtlCopyString(pointer_t destination, - pointer_t source) { +void RtlCopyString_entry(pointer_t destination, + pointer_t source) { if (!source) { destination->length = 0; return; @@ -199,8 +202,8 @@ void RtlCopyString(pointer_t destination, } DECLARE_XBOXKRNL_EXPORT1(RtlCopyString, kNone, kImplemented); -void RtlCopyUnicodeString(pointer_t destination, - pointer_t source) { +void RtlCopyUnicodeString_entry(pointer_t destination, + pointer_t source) { if (!source) { destination->length = 0; return; @@ -217,7 +220,7 @@ void RtlCopyUnicodeString(pointer_t destination, DECLARE_XBOXKRNL_EXPORT1(RtlCopyUnicodeString, kNone, kImplemented); // https://msdn.microsoft.com/en-us/library/ff562969 -dword_result_t RtlUnicodeStringToAnsiString( +dword_result_t RtlUnicodeStringToAnsiString_entry( pointer_t destination_ptr, pointer_t source_ptr, dword_t alloc_dest) { // NTSTATUS @@ -261,11 +264,11 @@ dword_result_t RtlUnicodeStringToAnsiString( DECLARE_XBOXKRNL_EXPORT1(RtlUnicodeStringToAnsiString, kNone, kImplemented); // https://msdn.microsoft.com/en-us/library/ff553113 -dword_result_t RtlMultiByteToUnicodeN(lpword_t destination_ptr, - dword_t destination_len, - lpdword_t written_ptr, - pointer_t source_ptr, - dword_t source_len) { +dword_result_t RtlMultiByteToUnicodeN_entry(lpword_t destination_ptr, + dword_t destination_len, + lpdword_t written_ptr, + pointer_t source_ptr, + dword_t source_len) { uint32_t copy_len = destination_len >> 1; copy_len = copy_len < source_len ? copy_len : source_len.value(); @@ -286,10 +289,11 @@ DECLARE_XBOXKRNL_EXPORT3(RtlMultiByteToUnicodeN, kNone, kImplemented, kHighFrequency, kSketchy); // https://msdn.microsoft.com/en-us/library/ff553261 -dword_result_t RtlUnicodeToMultiByteN(pointer_t destination_ptr, - dword_t destination_len, - lpdword_t written_ptr, - lpword_t source_ptr, dword_t source_len) { +dword_result_t RtlUnicodeToMultiByteN_entry(pointer_t destination_ptr, + dword_t destination_len, + lpdword_t written_ptr, + lpword_t source_ptr, + dword_t source_len) { uint32_t copy_len = source_len >> 1; copy_len = copy_len < destination_len ? copy_len : destination_len.value(); @@ -302,14 +306,13 @@ dword_result_t RtlUnicodeToMultiByteN(pointer_t destination_ptr, if (written_ptr.guest_address() != 0) { *written_ptr = copy_len; } - return 0; } DECLARE_XBOXKRNL_EXPORT3(RtlUnicodeToMultiByteN, kNone, kImplemented, kHighFrequency, kSketchy); // https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlImageNtHeader.html -pointer_result_t RtlImageNtHeader(lpvoid_t module) { +pointer_result_t RtlImageNtHeader_entry(lpvoid_t module) { if (!module) { return 0; } @@ -332,8 +335,8 @@ pointer_result_t RtlImageNtHeader(lpvoid_t module) { } DECLARE_XBOXKRNL_EXPORT1(RtlImageNtHeader, kNone, kImplemented); -pointer_result_t RtlImageXexHeaderField(pointer_t xex_header, - dword_t field_dword) { +pointer_result_t RtlImageXexHeaderField_entry(pointer_t xex_header, + dword_t field_dword) { uint32_t field_value = 0; uint32_t field = field_dword; // VS acts weird going from dword_t -> enum @@ -382,7 +385,7 @@ void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs, cs->owning_thread = 0; } -void RtlInitializeCriticalSection(pointer_t cs) { +void RtlInitializeCriticalSection_entry(pointer_t cs) { xeRtlInitializeCriticalSection(cs, cs.guest_address()); } DECLARE_XBOXKRNL_EXPORT1(RtlInitializeCriticalSection, kNone, kImplemented); @@ -407,7 +410,7 @@ X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs, return X_STATUS_SUCCESS; } -dword_result_t RtlInitializeCriticalSectionAndSpinCount( +dword_result_t RtlInitializeCriticalSectionAndSpinCount_entry( pointer_t cs, dword_t spin_count) { return xeRtlInitializeCriticalSectionAndSpinCount(cs, cs.guest_address(), spin_count); @@ -415,7 +418,7 @@ dword_result_t RtlInitializeCriticalSectionAndSpinCount( DECLARE_XBOXKRNL_EXPORT1(RtlInitializeCriticalSectionAndSpinCount, kNone, kImplemented); -void RtlEnterCriticalSection(pointer_t cs) { +void RtlEnterCriticalSection_entry(pointer_t cs) { uint32_t cur_thread = XThread::GetCurrentThread()->guest_object(); uint32_t spin_count = cs->header.absolute * 256; @@ -449,7 +452,7 @@ void RtlEnterCriticalSection(pointer_t cs) { DECLARE_XBOXKRNL_EXPORT2(RtlEnterCriticalSection, kNone, kImplemented, kHighFrequency); -dword_result_t RtlTryEnterCriticalSection( +dword_result_t RtlTryEnterCriticalSection_entry( pointer_t cs) { uint32_t thread = XThread::GetCurrentThread()->guest_object(); @@ -471,7 +474,7 @@ dword_result_t RtlTryEnterCriticalSection( DECLARE_XBOXKRNL_EXPORT2(RtlTryEnterCriticalSection, kNone, kImplemented, kHighFrequency); -void RtlLeaveCriticalSection(pointer_t cs) { +void RtlLeaveCriticalSection_entry(pointer_t cs) { assert_true(cs->owning_thread == XThread::GetCurrentThread()->guest_object()); // Drop recursion count - if it isn't zero we still have the lock. @@ -506,8 +509,8 @@ struct X_TIME_FIELDS { static_assert_size(X_TIME_FIELDS, 16); // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtltimetotimefields -void RtlTimeToTimeFields(lpqword_t time_ptr, - pointer_t time_fields_ptr) { +void RtlTimeToTimeFields_entry(lpqword_t time_ptr, + pointer_t time_fields_ptr) { auto tp = XClock::to_sys(XClock::from_file_time(time_ptr.value())); auto dp = date::floor(tp); auto year_month_day = date::year_month_day{dp}; @@ -526,12 +529,13 @@ void RtlTimeToTimeFields(lpqword_t time_ptr, DECLARE_XBOXKRNL_EXPORT1(RtlTimeToTimeFields, kNone, kImplemented); // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtltimefieldstotime -dword_result_t RtlTimeFieldsToTime(pointer_t time_fields_ptr, - lpqword_t time_ptr) { +dword_result_t RtlTimeFieldsToTime_entry( + pointer_t time_fields_ptr, lpqword_t time_ptr) { if (time_fields_ptr->year < 1601 || time_fields_ptr->month < 1 || - time_fields_ptr->month > 11 || time_fields_ptr->day < 1 || - time_fields_ptr->hour > 23 || time_fields_ptr->minute > 59 || - time_fields_ptr->second > 59 || time_fields_ptr->milliseconds > 999) { + time_fields_ptr->month > 12 || time_fields_ptr->day < 1 || + time_fields_ptr->day > 31 || time_fields_ptr->hour > 23 || + time_fields_ptr->minute > 59 || time_fields_ptr->second > 59 || + time_fields_ptr->milliseconds > 999) { return 0; } auto year = date::year{time_fields_ptr->year}; @@ -607,7 +611,8 @@ static uint32_t crc32_table[256] = { 0x2D02EF8Du, }; -dword_result_t RtlComputeCrc32(dword_t seed, lpvoid_t buffer, dword_t length) { +dword_result_t RtlComputeCrc32_entry(dword_t seed, lpvoid_t buffer, + dword_t length) { if (!length) { return seed.value(); } @@ -619,9 +624,8 @@ dword_result_t RtlComputeCrc32(dword_t seed, lpvoid_t buffer, dword_t length) { } DECLARE_XBOXKRNL_EXPORT1(RtlComputeCrc32, kNone, kImplemented); -void RegisterRtlExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Rtl); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc index 2cfcb50ac..1bab60f73 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -824,7 +824,7 @@ class WideCountFormatData : public FormatData { int32_t count_; }; -SHIM_CALL DbgPrint_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL DbgPrint_entry(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t format_ptr = SHIM_GET_ARG_32(0); if (!format_ptr) { SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER); @@ -854,7 +854,7 @@ SHIM_CALL DbgPrint_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/2ts7cx93.aspx -SHIM_CALL _snprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL _snprintf_entry(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); int32_t buffer_count = SHIM_GET_ARG_32(1); uint32_t format_ptr = SHIM_GET_ARG_32(2); @@ -894,7 +894,7 @@ SHIM_CALL _snprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/ybk95axf.aspx -SHIM_CALL sprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL sprintf_entry(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); uint32_t format_ptr = SHIM_GET_ARG_32(1); @@ -925,7 +925,7 @@ SHIM_CALL sprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/2ts7cx93.aspx -SHIM_CALL _snwprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL _snwprintf_entry(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); int32_t buffer_count = SHIM_GET_ARG_32(1); uint32_t format_ptr = SHIM_GET_ARG_32(2); @@ -966,7 +966,7 @@ SHIM_CALL _snwprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/ybk95axf.aspx -SHIM_CALL swprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL swprintf_entry(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); uint32_t format_ptr = SHIM_GET_ARG_32(1); @@ -998,7 +998,7 @@ SHIM_CALL swprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/1kt27hek.aspx -SHIM_CALL _vsnprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL _vsnprintf_entry(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); int32_t buffer_count = SHIM_GET_ARG_32(1); uint32_t format_ptr = SHIM_GET_ARG_32(2); @@ -1041,7 +1041,8 @@ SHIM_CALL _vsnprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/1kt27hek.aspx -SHIM_CALL _vsnwprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL _vsnwprintf_entry(PPCContext* ppc_context, + KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); int32_t buffer_count = SHIM_GET_ARG_32(1); uint32_t format_ptr = SHIM_GET_ARG_32(2); @@ -1086,7 +1087,7 @@ SHIM_CALL _vsnwprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/28d5ce15.aspx -SHIM_CALL vsprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL vsprintf_entry(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); uint32_t format_ptr = SHIM_GET_ARG_32(1); uint32_t arg_ptr = SHIM_GET_ARG_32(2); @@ -1118,7 +1119,8 @@ SHIM_CALL vsprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/w05tbk72.aspx -SHIM_CALL _vscwprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL _vscwprintf_entry(PPCContext* ppc_context, + KernelState* kernel_state) { uint32_t format_ptr = SHIM_GET_ARG_32(0); uint32_t arg_ptr = SHIM_GET_ARG_32(1); @@ -1145,7 +1147,7 @@ SHIM_CALL _vscwprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { } // https://msdn.microsoft.com/en-us/library/28d5ce15.aspx -SHIM_CALL vswprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { +SHIM_CALL vswprintf_entry(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); uint32_t format_ptr = SHIM_GET_ARG_32(1); uint32_t arg_ptr = SHIM_GET_ARG_32(2); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc index 3a323d579..f913643eb 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -95,11 +95,12 @@ object_ref LookupNamedObject(KernelState* kernel_state, return nullptr; } -dword_result_t ExCreateThread(lpdword_t handle_ptr, dword_t stack_size, - lpdword_t thread_id_ptr, - dword_t xapi_thread_startup, - lpvoid_t start_address, lpvoid_t start_context, - dword_t creation_flags) { +dword_result_t ExCreateThread_entry(lpdword_t handle_ptr, dword_t stack_size, + lpdword_t thread_id_ptr, + dword_t xapi_thread_startup, + lpvoid_t start_address, + lpvoid_t start_context, + dword_t creation_flags) { // http://jafile.com/uploads/scoop/main.cpp.txt // DWORD // LPHANDLE Handle, @@ -149,7 +150,7 @@ dword_result_t ExCreateThread(lpdword_t handle_ptr, dword_t stack_size, } DECLARE_XBOXKRNL_EXPORT1(ExCreateThread, kThreading, kImplemented); -dword_result_t ExTerminateThread(dword_t exit_code) { +dword_result_t ExTerminateThread_entry(dword_t exit_code) { XThread* thread = XThread::GetCurrentThread(); // NOTE: this kills us right now. We won't return from it. @@ -157,7 +158,8 @@ dword_result_t ExTerminateThread(dword_t exit_code) { } DECLARE_XBOXKRNL_EXPORT1(ExTerminateThread, kThreading, kImplemented); -dword_result_t NtResumeThread(dword_t handle, lpdword_t suspend_count_ptr) { +dword_result_t NtResumeThread_entry(dword_t handle, + lpdword_t suspend_count_ptr) { X_RESULT result = X_STATUS_INVALID_HANDLE; uint32_t suspend_count = 0; @@ -173,7 +175,7 @@ dword_result_t NtResumeThread(dword_t handle, lpdword_t suspend_count_ptr) { } DECLARE_XBOXKRNL_EXPORT1(NtResumeThread, kThreading, kImplemented); -dword_result_t KeResumeThread(lpvoid_t thread_ptr) { +dword_result_t KeResumeThread_entry(lpvoid_t thread_ptr) { X_STATUS result = X_STATUS_SUCCESS; auto thread = XObject::GetNativeObject(kernel_state(), thread_ptr); if (thread) { @@ -186,7 +188,8 @@ dword_result_t KeResumeThread(lpvoid_t thread_ptr) { } DECLARE_XBOXKRNL_EXPORT1(KeResumeThread, kThreading, kImplemented); -dword_result_t NtSuspendThread(dword_t handle, lpdword_t suspend_count_ptr) { +dword_result_t NtSuspendThread_entry(dword_t handle, + lpdword_t suspend_count_ptr) { X_RESULT result = X_STATUS_SUCCESS; uint32_t suspend_count = 0; @@ -205,9 +208,11 @@ dword_result_t NtSuspendThread(dword_t handle, lpdword_t suspend_count_ptr) { } DECLARE_XBOXKRNL_EXPORT1(NtSuspendThread, kThreading, kImplemented); -void KeSetCurrentStackPointers(lpvoid_t stack_ptr, pointer_t thread, - lpvoid_t stack_alloc_base, lpvoid_t stack_base, - lpvoid_t stack_limit) { +void KeSetCurrentStackPointers_entry(lpvoid_t stack_ptr, + pointer_t thread, + lpvoid_t stack_alloc_base, + lpvoid_t stack_base, + lpvoid_t stack_limit) { auto current_thread = XThread::GetCurrentThread(); auto context = current_thread->thread_state()->context(); auto pcr = kernel_memory()->TranslateVirtual( @@ -230,8 +235,8 @@ void KeSetCurrentStackPointers(lpvoid_t stack_ptr, pointer_t thread, DECLARE_XBOXKRNL_EXPORT2(KeSetCurrentStackPointers, kThreading, kImplemented, kHighFrequency); -dword_result_t KeSetAffinityThread(lpvoid_t thread_ptr, dword_t affinity, - lpdword_t previous_affinity_ptr) { +dword_result_t KeSetAffinityThread_entry(lpvoid_t thread_ptr, dword_t affinity, + lpdword_t previous_affinity_ptr) { // The Xbox 360, according to disassembly of KeSetAffinityThread, unlike // Windows NT, stores the previous affinity via the pointer provided as an // argument, not in the return value - the return value is used for the @@ -250,7 +255,7 @@ dword_result_t KeSetAffinityThread(lpvoid_t thread_ptr, dword_t affinity, } DECLARE_XBOXKRNL_EXPORT1(KeSetAffinityThread, kThreading, kImplemented); -dword_result_t KeQueryBasePriorityThread(lpvoid_t thread_ptr) { +dword_result_t KeQueryBasePriorityThread_entry(lpvoid_t thread_ptr) { int32_t priority = 0; auto thread = XObject::GetNativeObject(kernel_state(), thread_ptr); @@ -262,7 +267,8 @@ dword_result_t KeQueryBasePriorityThread(lpvoid_t thread_ptr) { } DECLARE_XBOXKRNL_EXPORT1(KeQueryBasePriorityThread, kThreading, kImplemented); -dword_result_t KeSetBasePriorityThread(lpvoid_t thread_ptr, dword_t increment) { +dword_result_t KeSetBasePriorityThread_entry(lpvoid_t thread_ptr, + dword_t increment) { int32_t prev_priority = 0; auto thread = XObject::GetNativeObject(kernel_state(), thread_ptr); @@ -275,7 +281,8 @@ dword_result_t KeSetBasePriorityThread(lpvoid_t thread_ptr, dword_t increment) { } DECLARE_XBOXKRNL_EXPORT1(KeSetBasePriorityThread, kThreading, kImplemented); -dword_result_t KeSetDisableBoostThread(lpvoid_t thread_ptr, dword_t disabled) { +dword_result_t KeSetDisableBoostThread_entry(lpvoid_t thread_ptr, + dword_t disabled) { auto thread = XObject::GetNativeObject(kernel_state(), thread_ptr); if (thread) { // Uhm? @@ -285,13 +292,13 @@ dword_result_t KeSetDisableBoostThread(lpvoid_t thread_ptr, dword_t disabled) { } DECLARE_XBOXKRNL_EXPORT1(KeSetDisableBoostThread, kThreading, kImplemented); -dword_result_t KeGetCurrentProcessType() { +dword_result_t KeGetCurrentProcessType_entry() { return kernel_state()->process_type(); } DECLARE_XBOXKRNL_EXPORT2(KeGetCurrentProcessType, kThreading, kImplemented, kHighFrequency); -void KeSetCurrentProcessType(dword_t type) { +void KeSetCurrentProcessType_entry(dword_t type) { // One of X_PROCTYPE_? assert_true(type <= 2); @@ -300,15 +307,16 @@ void KeSetCurrentProcessType(dword_t type) { } DECLARE_XBOXKRNL_EXPORT1(KeSetCurrentProcessType, kThreading, kImplemented); -dword_result_t KeQueryPerformanceFrequency() { +dword_result_t KeQueryPerformanceFrequency_entry() { uint64_t result = Clock::guest_tick_frequency(); return static_cast(result); } DECLARE_XBOXKRNL_EXPORT2(KeQueryPerformanceFrequency, kThreading, kImplemented, kHighFrequency); -dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable, - lpqword_t interval_ptr) { +dword_result_t KeDelayExecutionThread_entry(dword_t processor_mode, + dword_t alertable, + lpqword_t interval_ptr) { XThread* thread = XThread::GetCurrentThread(); X_STATUS result = thread->Delay(processor_mode, alertable, *interval_ptr); @@ -317,7 +325,7 @@ dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable, DECLARE_XBOXKRNL_EXPORT3(KeDelayExecutionThread, kThreading, kImplemented, kBlocking, kHighFrequency); -dword_result_t NtYieldExecution() { +dword_result_t NtYieldExecution_entry() { auto thread = XThread::GetCurrentThread(); thread->Delay(0, 0, 0); return 0; @@ -325,7 +333,7 @@ dword_result_t NtYieldExecution() { DECLARE_XBOXKRNL_EXPORT2(NtYieldExecution, kThreading, kImplemented, kHighFrequency); -void KeQuerySystemTime(lpqword_t time_ptr) { +void KeQuerySystemTime_entry(lpqword_t time_ptr) { uint64_t time = Clock::QueryGuestSystemTime(); if (time_ptr) { *time_ptr = time; @@ -334,7 +342,7 @@ void KeQuerySystemTime(lpqword_t time_ptr) { DECLARE_XBOXKRNL_EXPORT1(KeQuerySystemTime, kThreading, kImplemented); // https://msdn.microsoft.com/en-us/library/ms686801 -dword_result_t KeTlsAlloc() { +dword_result_t KeTlsAlloc_entry() { uint32_t slot = kernel_state()->AllocateTLS(); XThread::GetCurrentThread()->SetTLSValue(slot, 0); @@ -343,7 +351,7 @@ dword_result_t KeTlsAlloc() { DECLARE_XBOXKRNL_EXPORT1(KeTlsAlloc, kThreading, kImplemented); // https://msdn.microsoft.com/en-us/library/ms686804 -dword_result_t KeTlsFree(dword_t tls_index) { +dword_result_t KeTlsFree_entry(dword_t tls_index) { if (tls_index == X_TLS_OUT_OF_INDEXES) { return 0; } @@ -354,7 +362,7 @@ dword_result_t KeTlsFree(dword_t tls_index) { DECLARE_XBOXKRNL_EXPORT1(KeTlsFree, kThreading, kImplemented); // https://msdn.microsoft.com/en-us/library/ms686812 -dword_result_t KeTlsGetValue(dword_t tls_index) { +dword_result_t KeTlsGetValue_entry(dword_t tls_index) { // xboxkrnl doesn't actually have an error branch - it always succeeds, even // if it overflows the TLS. uint32_t value = 0; @@ -368,7 +376,7 @@ DECLARE_XBOXKRNL_EXPORT2(KeTlsGetValue, kThreading, kImplemented, kHighFrequency); // https://msdn.microsoft.com/en-us/library/ms686818 -dword_result_t KeTlsSetValue(dword_t tls_index, dword_t tls_value) { +dword_result_t KeTlsSetValue_entry(dword_t tls_index, dword_t tls_value) { // xboxkrnl doesn't actually have an error branch - it always succeeds, even // if it overflows the TLS. if (XThread::GetCurrentThread()->SetTLSValue(tls_index, tls_value)) { @@ -379,8 +387,8 @@ dword_result_t KeTlsSetValue(dword_t tls_index, dword_t tls_value) { } DECLARE_XBOXKRNL_EXPORT1(KeTlsSetValue, kThreading, kImplemented); -void KeInitializeEvent(pointer_t event_ptr, dword_t event_type, - dword_t initial_state) { +void KeInitializeEvent_entry(pointer_t event_ptr, dword_t event_type, + dword_t initial_state) { event_ptr.Zero(); event_ptr->header.type = event_type; event_ptr->header.signal_state = (uint32_t)initial_state; @@ -403,14 +411,14 @@ uint32_t xeKeSetEvent(X_KEVENT* event_ptr, uint32_t increment, uint32_t wait) { return ev->Set(increment, !!wait); } -dword_result_t KeSetEvent(pointer_t event_ptr, dword_t increment, - dword_t wait) { +dword_result_t KeSetEvent_entry(pointer_t event_ptr, + dword_t increment, dword_t wait) { return xeKeSetEvent(event_ptr, increment, wait); } DECLARE_XBOXKRNL_EXPORT2(KeSetEvent, kThreading, kImplemented, kHighFrequency); -dword_result_t KePulseEvent(pointer_t event_ptr, dword_t increment, - dword_t wait) { +dword_result_t KePulseEvent_entry(pointer_t event_ptr, + dword_t increment, dword_t wait) { auto ev = XObject::GetNativeObject(kernel_state(), event_ptr); if (!ev) { assert_always(); @@ -422,7 +430,7 @@ dword_result_t KePulseEvent(pointer_t event_ptr, dword_t increment, DECLARE_XBOXKRNL_EXPORT2(KePulseEvent, kThreading, kImplemented, kHighFrequency); -dword_result_t KeResetEvent(pointer_t event_ptr) { +dword_result_t KeResetEvent_entry(pointer_t event_ptr) { auto ev = XObject::GetNativeObject(kernel_state(), event_ptr); if (!ev) { assert_always(); @@ -433,9 +441,9 @@ dword_result_t KeResetEvent(pointer_t event_ptr) { } DECLARE_XBOXKRNL_EXPORT1(KeResetEvent, kThreading, kImplemented); -dword_result_t NtCreateEvent(lpdword_t handle_ptr, - pointer_t obj_attributes_ptr, - dword_t event_type, dword_t initial_state) { +dword_result_t NtCreateEvent_entry( + lpdword_t handle_ptr, pointer_t obj_attributes_ptr, + dword_t event_type, dword_t initial_state) { // Check for an existing timer with the same name. auto existing_object = LookupNamedObject(kernel_state(), obj_attributes_ptr); @@ -482,12 +490,13 @@ uint32_t xeNtSetEvent(uint32_t handle, xe::be* previous_state_ptr) { return result; } -dword_result_t NtSetEvent(dword_t handle, lpdword_t previous_state_ptr) { +dword_result_t NtSetEvent_entry(dword_t handle, lpdword_t previous_state_ptr) { return xeNtSetEvent(handle, previous_state_ptr); } DECLARE_XBOXKRNL_EXPORT2(NtSetEvent, kThreading, kImplemented, kHighFrequency); -dword_result_t NtPulseEvent(dword_t handle, lpdword_t previous_state_ptr) { +dword_result_t NtPulseEvent_entry(dword_t handle, + lpdword_t previous_state_ptr) { X_STATUS result = X_STATUS_SUCCESS; auto ev = kernel_state()->object_table()->LookupObject(handle); @@ -518,13 +527,15 @@ uint32_t xeNtClearEvent(uint32_t handle) { return result; } -dword_result_t NtClearEvent(dword_t handle) { return xeNtClearEvent(handle); } +dword_result_t NtClearEvent_entry(dword_t handle) { + return xeNtClearEvent(handle); +} DECLARE_XBOXKRNL_EXPORT2(NtClearEvent, kThreading, kImplemented, kHighFrequency); // https://msdn.microsoft.com/en-us/library/windows/hardware/ff552150(v=vs.85).aspx -void KeInitializeSemaphore(pointer_t semaphore_ptr, dword_t count, - dword_t limit) { +void KeInitializeSemaphore_entry(pointer_t semaphore_ptr, + dword_t count, dword_t limit) { semaphore_ptr->header.type = 5; // SemaphoreObject semaphore_ptr->header.signal_state = (uint32_t)count; semaphore_ptr->limit = (uint32_t)limit; @@ -553,16 +564,16 @@ uint32_t xeKeReleaseSemaphore(X_KSEMAPHORE* semaphore_ptr, uint32_t increment, return sem->ReleaseSemaphore(adjustment); } -dword_result_t KeReleaseSemaphore(pointer_t semaphore_ptr, - dword_t increment, dword_t adjustment, - dword_t wait) { +dword_result_t KeReleaseSemaphore_entry(pointer_t semaphore_ptr, + dword_t increment, dword_t adjustment, + dword_t wait) { return xeKeReleaseSemaphore(semaphore_ptr, increment, adjustment, wait); } DECLARE_XBOXKRNL_EXPORT1(KeReleaseSemaphore, kThreading, kImplemented); -dword_result_t NtCreateSemaphore(lpdword_t handle_ptr, - lpvoid_t obj_attributes_ptr, dword_t count, - dword_t limit) { +dword_result_t NtCreateSemaphore_entry(lpdword_t handle_ptr, + lpvoid_t obj_attributes_ptr, + dword_t count, dword_t limit) { // Check for an existing timer with the same name. auto existing_object = LookupNamedObject(kernel_state(), obj_attributes_ptr); @@ -594,8 +605,9 @@ dword_result_t NtCreateSemaphore(lpdword_t handle_ptr, } DECLARE_XBOXKRNL_EXPORT1(NtCreateSemaphore, kThreading, kImplemented); -dword_result_t NtReleaseSemaphore(dword_t sem_handle, dword_t release_count, - lpdword_t previous_count_ptr) { +dword_result_t NtReleaseSemaphore_entry(dword_t sem_handle, + dword_t release_count, + lpdword_t previous_count_ptr) { X_STATUS result = X_STATUS_SUCCESS; int32_t previous_count = 0; @@ -612,11 +624,12 @@ dword_result_t NtReleaseSemaphore(dword_t sem_handle, dword_t release_count, return result; } -DECLARE_XBOXKRNL_EXPORT1(NtReleaseSemaphore, kThreading, kImplemented); +DECLARE_XBOXKRNL_EXPORT2(NtReleaseSemaphore, kThreading, kImplemented, + kHighFrequency); -dword_result_t NtCreateMutant(lpdword_t handle_out, - pointer_t obj_attributes, - dword_t initial_owner) { +dword_result_t NtCreateMutant_entry( + lpdword_t handle_out, pointer_t obj_attributes, + dword_t initial_owner) { // Check for an existing timer with the same name. auto existing_object = LookupNamedObject( kernel_state(), obj_attributes.guest_address()); @@ -648,7 +661,7 @@ dword_result_t NtCreateMutant(lpdword_t handle_out, } DECLARE_XBOXKRNL_EXPORT1(NtCreateMutant, kThreading, kImplemented); -dword_result_t NtReleaseMutant(dword_t mutant_handle, dword_t unknown) { +dword_result_t NtReleaseMutant_entry(dword_t mutant_handle, dword_t unknown) { // This doesn't seem to be supported. // int32_t previous_count_ptr = SHIM_GET_ARG_32(2); @@ -674,8 +687,9 @@ dword_result_t NtReleaseMutant(dword_t mutant_handle, dword_t unknown) { } DECLARE_XBOXKRNL_EXPORT1(NtReleaseMutant, kThreading, kImplemented); -dword_result_t NtCreateTimer(lpdword_t handle_ptr, lpvoid_t obj_attributes_ptr, - dword_t timer_type) { +dword_result_t NtCreateTimer_entry(lpdword_t handle_ptr, + lpvoid_t obj_attributes_ptr, + dword_t timer_type) { // timer_type = NotificationTimer (0) or SynchronizationTimer (1) // Check for an existing timer with the same name. @@ -709,11 +723,11 @@ dword_result_t NtCreateTimer(lpdword_t handle_ptr, lpvoid_t obj_attributes_ptr, } DECLARE_XBOXKRNL_EXPORT1(NtCreateTimer, kThreading, kImplemented); -dword_result_t NtSetTimerEx(dword_t timer_handle, lpqword_t due_time_ptr, - lpvoid_t routine_ptr /*PTIMERAPCROUTINE*/, - dword_t unk_one, lpvoid_t routine_arg, - dword_t resume, dword_t period_ms, - dword_t unk_zero) { +dword_result_t NtSetTimerEx_entry(dword_t timer_handle, lpqword_t due_time_ptr, + lpvoid_t routine_ptr /*PTIMERAPCROUTINE*/, + dword_t unk_one, lpvoid_t routine_arg, + dword_t resume, dword_t period_ms, + dword_t unk_zero) { assert_true(unk_one == 1); assert_true(unk_zero == 0); @@ -735,8 +749,8 @@ dword_result_t NtSetTimerEx(dword_t timer_handle, lpqword_t due_time_ptr, } DECLARE_XBOXKRNL_EXPORT1(NtSetTimerEx, kThreading, kImplemented); -dword_result_t NtCancelTimer(dword_t timer_handle, - lpdword_t current_state_ptr) { +dword_result_t NtCancelTimer_entry(dword_t timer_handle, + lpdword_t current_state_ptr) { X_STATUS result = X_STATUS_SUCCESS; auto timer = @@ -771,9 +785,11 @@ uint32_t xeKeWaitForSingleObject(void* object_ptr, uint32_t wait_reason, return result; } -dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason, - dword_t processor_mode, dword_t alertable, - lpqword_t timeout_ptr) { +dword_result_t KeWaitForSingleObject_entry(lpvoid_t object_ptr, + dword_t wait_reason, + dword_t processor_mode, + dword_t alertable, + lpqword_t timeout_ptr) { uint64_t timeout = timeout_ptr ? static_cast(*timeout_ptr) : 0u; return xeKeWaitForSingleObject(object_ptr, wait_reason, processor_mode, alertable, timeout_ptr ? &timeout : nullptr); @@ -781,9 +797,10 @@ dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason, DECLARE_XBOXKRNL_EXPORT3(KeWaitForSingleObject, kThreading, kImplemented, kBlocking, kHighFrequency); -dword_result_t NtWaitForSingleObjectEx(dword_t object_handle, dword_t wait_mode, - dword_t alertable, - lpqword_t timeout_ptr) { +dword_result_t NtWaitForSingleObjectEx_entry(dword_t object_handle, + dword_t wait_mode, + dword_t alertable, + lpqword_t timeout_ptr) { X_STATUS result = X_STATUS_SUCCESS; auto object = @@ -801,12 +818,10 @@ dword_result_t NtWaitForSingleObjectEx(dword_t object_handle, dword_t wait_mode, DECLARE_XBOXKRNL_EXPORT3(NtWaitForSingleObjectEx, kThreading, kImplemented, kBlocking, kHighFrequency); -dword_result_t KeWaitForMultipleObjects(dword_t count, lpdword_t objects_ptr, - dword_t wait_type, dword_t wait_reason, - dword_t processor_mode, - dword_t alertable, - lpqword_t timeout_ptr, - lpvoid_t wait_block_array_ptr) { +dword_result_t KeWaitForMultipleObjects_entry( + dword_t count, lpdword_t objects_ptr, dword_t wait_type, + dword_t wait_reason, dword_t processor_mode, dword_t alertable, + lpqword_t timeout_ptr, lpvoid_t wait_block_array_ptr) { assert_true(wait_type <= 1); std::vector> objects; @@ -852,10 +867,9 @@ uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be* handles, wait_type, 6, wait_mode, alertable, timeout_ptr); } -dword_result_t NtWaitForMultipleObjectsEx(dword_t count, lpdword_t handles, - dword_t wait_type, dword_t wait_mode, - dword_t alertable, - lpqword_t timeout_ptr) { +dword_result_t NtWaitForMultipleObjectsEx_entry( + dword_t count, lpdword_t handles, dword_t wait_type, dword_t wait_mode, + dword_t alertable, lpqword_t timeout_ptr) { uint64_t timeout = timeout_ptr ? static_cast(*timeout_ptr) : 0u; return xeNtWaitForMultipleObjectsEx(count, handles, wait_type, wait_mode, alertable, @@ -864,10 +878,11 @@ dword_result_t NtWaitForMultipleObjectsEx(dword_t count, lpdword_t handles, DECLARE_XBOXKRNL_EXPORT3(NtWaitForMultipleObjectsEx, kThreading, kImplemented, kBlocking, kHighFrequency); -dword_result_t NtSignalAndWaitForSingleObjectEx(dword_t signal_handle, - dword_t wait_handle, - dword_t alertable, dword_t r6, - lpqword_t timeout_ptr) { +dword_result_t NtSignalAndWaitForSingleObjectEx_entry(dword_t signal_handle, + dword_t wait_handle, + dword_t alertable, + dword_t r6, + lpqword_t timeout_ptr) { X_STATUS result = X_STATUS_SUCCESS; auto signal_object = @@ -907,7 +922,7 @@ uint32_t xeKeKfAcquireSpinLock(uint32_t* lock) { return old_irql; } -dword_result_t KfAcquireSpinLock(lpdword_t lock_ptr) { +dword_result_t KfAcquireSpinLock_entry(lpdword_t lock_ptr) { auto lock = reinterpret_cast(lock_ptr.host_address()); return xeKeKfAcquireSpinLock(lock); } @@ -923,14 +938,14 @@ void xeKeKfReleaseSpinLock(uint32_t* lock, dword_t old_irql) { xe::atomic_dec(lock); } -void KfReleaseSpinLock(lpdword_t lock_ptr, dword_t old_irql) { +void KfReleaseSpinLock_entry(lpdword_t lock_ptr, dword_t old_irql) { auto lock = reinterpret_cast(lock_ptr.host_address()); xeKeKfReleaseSpinLock(lock, old_irql); } DECLARE_XBOXKRNL_EXPORT2(KfReleaseSpinLock, kThreading, kImplemented, kHighFrequency); -void KeAcquireSpinLockAtRaisedIrql(lpdword_t lock_ptr) { +void KeAcquireSpinLockAtRaisedIrql_entry(lpdword_t lock_ptr) { // Lock. auto lock = reinterpret_cast(lock_ptr.host_address()); while (!xe::atomic_cas(0, 1, lock)) { @@ -941,7 +956,7 @@ void KeAcquireSpinLockAtRaisedIrql(lpdword_t lock_ptr) { DECLARE_XBOXKRNL_EXPORT3(KeAcquireSpinLockAtRaisedIrql, kThreading, kImplemented, kBlocking, kHighFrequency); -dword_result_t KeTryToAcquireSpinLockAtRaisedIrql(lpdword_t lock_ptr) { +dword_result_t KeTryToAcquireSpinLockAtRaisedIrql_entry(lpdword_t lock_ptr) { // Lock. auto lock = reinterpret_cast(lock_ptr.host_address()); if (!xe::atomic_cas(0, 1, lock)) { @@ -952,7 +967,7 @@ dword_result_t KeTryToAcquireSpinLockAtRaisedIrql(lpdword_t lock_ptr) { DECLARE_XBOXKRNL_EXPORT4(KeTryToAcquireSpinLockAtRaisedIrql, kThreading, kImplemented, kBlocking, kHighFrequency, kSketchy); -void KeReleaseSpinLockFromRaisedIrql(lpdword_t lock_ptr) { +void KeReleaseSpinLockFromRaisedIrql_entry(lpdword_t lock_ptr) { // Unlock. auto lock = reinterpret_cast(lock_ptr.host_address()); xe::atomic_dec(lock); @@ -960,26 +975,26 @@ void KeReleaseSpinLockFromRaisedIrql(lpdword_t lock_ptr) { DECLARE_XBOXKRNL_EXPORT2(KeReleaseSpinLockFromRaisedIrql, kThreading, kImplemented, kHighFrequency); -void KeEnterCriticalRegion() { +void KeEnterCriticalRegion_entry() { XThread::GetCurrentThread()->EnterCriticalRegion(); } DECLARE_XBOXKRNL_EXPORT2(KeEnterCriticalRegion, kThreading, kImplemented, kHighFrequency); -void KeLeaveCriticalRegion() { +void KeLeaveCriticalRegion_entry() { XThread::GetCurrentThread()->LeaveCriticalRegion(); } DECLARE_XBOXKRNL_EXPORT2(KeLeaveCriticalRegion, kThreading, kImplemented, kHighFrequency); -dword_result_t KeRaiseIrqlToDpcLevel() { +dword_result_t KeRaiseIrqlToDpcLevel_entry() { auto old_value = kernel_state()->processor()->RaiseIrql(cpu::Irql::DPC); return (uint32_t)old_value; } DECLARE_XBOXKRNL_EXPORT2(KeRaiseIrqlToDpcLevel, kThreading, kImplemented, kHighFrequency); -void KfLowerIrql(dword_t old_value) { +void KfLowerIrql_entry(dword_t old_value) { kernel_state()->processor()->LowerIrql( static_cast((uint32_t)old_value)); @@ -987,9 +1002,9 @@ void KfLowerIrql(dword_t old_value) { } DECLARE_XBOXKRNL_EXPORT2(KfLowerIrql, kThreading, kImplemented, kHighFrequency); -void NtQueueApcThread(dword_t thread_handle, lpvoid_t apc_routine, - lpvoid_t apc_routine_context, lpvoid_t arg1, - lpvoid_t arg2) { +void NtQueueApcThread_entry(dword_t thread_handle, lpvoid_t apc_routine, + lpvoid_t apc_routine_context, lpvoid_t arg1, + lpvoid_t arg2) { auto thread = kernel_state()->object_table()->LookupObject(thread_handle); @@ -1007,10 +1022,10 @@ void NtQueueApcThread(dword_t thread_handle, lpvoid_t apc_routine, } DECLARE_XBOXKRNL_EXPORT1(NtQueueApcThread, kThreading, kImplemented); -void KeInitializeApc(pointer_t apc, lpvoid_t thread_ptr, - lpvoid_t kernel_routine, lpvoid_t rundown_routine, - lpvoid_t normal_routine, dword_t processor_mode, - lpvoid_t normal_context) { +void KeInitializeApc_entry(pointer_t apc, lpvoid_t thread_ptr, + lpvoid_t kernel_routine, lpvoid_t rundown_routine, + lpvoid_t normal_routine, dword_t processor_mode, + lpvoid_t normal_context) { apc->Initialize(); apc->processor_mode = processor_mode; apc->thread_ptr = thread_ptr.guest_address(); @@ -1022,8 +1037,9 @@ void KeInitializeApc(pointer_t apc, lpvoid_t thread_ptr, } DECLARE_XBOXKRNL_EXPORT1(KeInitializeApc, kThreading, kImplemented); -dword_result_t KeInsertQueueApc(pointer_t apc, lpvoid_t arg1, - lpvoid_t arg2, dword_t priority_increment) { +dword_result_t KeInsertQueueApc_entry(pointer_t apc, lpvoid_t arg1, + lpvoid_t arg2, + dword_t priority_increment) { auto thread = XObject::GetNativeObject( kernel_state(), kernel_state()->memory()->TranslateVirtual(apc->thread_ptr)); @@ -1057,7 +1073,7 @@ dword_result_t KeInsertQueueApc(pointer_t apc, lpvoid_t arg1, } DECLARE_XBOXKRNL_EXPORT1(KeInsertQueueApc, kThreading, kImplemented); -dword_result_t KeRemoveQueueApc(pointer_t apc) { +dword_result_t KeRemoveQueueApc_entry(pointer_t apc) { bool result = false; auto thread = XObject::GetNativeObject( @@ -1087,8 +1103,8 @@ dword_result_t KeRemoveQueueApc(pointer_t apc) { } DECLARE_XBOXKRNL_EXPORT1(KeRemoveQueueApc, kThreading, kImplemented); -dword_result_t KiApcNormalRoutineNop(dword_t unk0 /* output? */, - dword_t unk1 /* 0x13 */) { +dword_result_t KiApcNormalRoutineNop_entry(dword_t unk0 /* output? */, + dword_t unk1 /* 0x13 */) { return 0; } DECLARE_XBOXKRNL_EXPORT1(KiApcNormalRoutineNop, kThreading, kStub); @@ -1103,7 +1119,8 @@ typedef struct { xe::be arg2; } XDPC; -void KeInitializeDpc(pointer_t dpc, lpvoid_t routine, lpvoid_t context) { +void KeInitializeDpc_entry(pointer_t dpc, lpvoid_t routine, + lpvoid_t context) { // KDPC (maybe) 0x18 bytes? uint32_t type = 19; // DpcObject uint32_t importance = 0; @@ -1118,8 +1135,8 @@ void KeInitializeDpc(pointer_t dpc, lpvoid_t routine, lpvoid_t context) { } DECLARE_XBOXKRNL_EXPORT2(KeInitializeDpc, kThreading, kImplemented, kSketchy); -dword_result_t KeInsertQueueDpc(pointer_t dpc, dword_t arg1, - dword_t arg2) { +dword_result_t KeInsertQueueDpc_entry(pointer_t dpc, dword_t arg1, + dword_t arg2) { assert_always("DPC does not dispatch yet; going to hang!"); uint32_t list_entry_ptr = dpc.guest_address() + 4; @@ -1143,7 +1160,7 @@ dword_result_t KeInsertQueueDpc(pointer_t dpc, dword_t arg1, } DECLARE_XBOXKRNL_EXPORT2(KeInsertQueueDpc, kThreading, kStub, kSketchy); -dword_result_t KeRemoveQueueDpc(pointer_t dpc) { +dword_result_t KeRemoveQueueDpc_entry(pointer_t dpc) { bool result = false; uint32_t list_entry_ptr = dpc.guest_address() + 4; @@ -1171,37 +1188,98 @@ struct X_ERWLOCK { }; static_assert_size(X_ERWLOCK, 0x38); -void ExInitializeReadWriteLock(pointer_t lock_ptr) { +void ExInitializeReadWriteLock_entry(pointer_t lock_ptr) { lock_ptr->lock_count = -1; lock_ptr->writers_waiting_count = 0; lock_ptr->readers_waiting_count = 0; lock_ptr->readers_entry_count = 0; - KeInitializeEvent(&lock_ptr->writer_event, 1, 0); - KeInitializeSemaphore(&lock_ptr->reader_semaphore, 0, 0x7FFFFFFF); + KeInitializeEvent_entry(&lock_ptr->writer_event, 1, 0); + KeInitializeSemaphore_entry(&lock_ptr->reader_semaphore, 0, 0x7FFFFFFF); lock_ptr->spin_lock = 0; } DECLARE_XBOXKRNL_EXPORT1(ExInitializeReadWriteLock, kThreading, kImplemented); -void ExAcquireReadWriteLockExclusive(pointer_t lock_ptr) { +void ExAcquireReadWriteLockExclusive_entry(pointer_t lock_ptr) { auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock); - lock_ptr->lock_count++; - xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); - if (!lock_ptr->lock_count) { + int32_t lock_count = ++lock_ptr->lock_count; + if (!lock_count) { + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); return; } lock_ptr->writers_waiting_count++; - xeKeWaitForSingleObject(&lock_ptr->writer_event, 0, 0, 0, nullptr); + + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + xeKeWaitForSingleObject(&lock_ptr->writer_event, 7, 0, 0, nullptr); } -DECLARE_XBOXKRNL_EXPORT3(ExAcquireReadWriteLockExclusive, kThreading, - kImplemented, kBlocking, kSketchy); +DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockExclusive, kThreading, + kImplemented, kBlocking); -void ExReleaseReadWriteLock(pointer_t lock_ptr) { +dword_result_t ExTryToAcquireReadWriteLockExclusive_entry( + pointer_t lock_ptr) { auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock); - lock_ptr->lock_count--; + uint32_t result; if (lock_ptr->lock_count < 0) { + lock_ptr->lock_count = 0; + result = 1; + } else { + result = 0; + } + + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + return result; +} +DECLARE_XBOXKRNL_EXPORT1(ExTryToAcquireReadWriteLockExclusive, kThreading, + kImplemented); + +void ExAcquireReadWriteLockShared_entry(pointer_t lock_ptr) { + auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock); + + int32_t lock_count = ++lock_ptr->lock_count; + if (!lock_count || + (lock_ptr->readers_entry_count && !lock_ptr->writers_waiting_count)) { + lock_ptr->readers_entry_count++; + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + return; + } + + lock_ptr->readers_waiting_count++; + + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + xeKeWaitForSingleObject(&lock_ptr->reader_semaphore, 7, 0, 0, nullptr); +} +DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockShared, kThreading, kImplemented, + kBlocking); + +dword_result_t ExTryToAcquireReadWriteLockShared_entry( + pointer_t lock_ptr) { + auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock); + + uint32_t result; + if (lock_ptr->lock_count < 0 || + (lock_ptr->readers_entry_count && !lock_ptr->writers_waiting_count)) { + lock_ptr->lock_count++; + lock_ptr->readers_entry_count++; + result = 1; + } else { + result = 0; + } + + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + return result; +} +DECLARE_XBOXKRNL_EXPORT1(ExTryToAcquireReadWriteLockShared, kThreading, + kImplemented); + +void ExReleaseReadWriteLock_entry(pointer_t lock_ptr) { + auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock); + + int32_t lock_count = --lock_ptr->lock_count; + + if (lock_count < 0) { + lock_ptr->readers_entry_count = 0; xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); return; } @@ -1218,17 +1296,20 @@ void ExReleaseReadWriteLock(pointer_t lock_ptr) { } } - auto count = lock_ptr->readers_entry_count--; - xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); - if (!count) { - xeKeSetEvent(&lock_ptr->writer_event, 1, 0); + auto readers_entry_count = --lock_ptr->readers_entry_count; + if (readers_entry_count) { + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + return; } + + lock_ptr->writers_waiting_count--; + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + xeKeSetEvent(&lock_ptr->writer_event, 1, 0); } -DECLARE_XBOXKRNL_EXPORT2(ExReleaseReadWriteLock, kThreading, kImplemented, - kSketchy); +DECLARE_XBOXKRNL_EXPORT1(ExReleaseReadWriteLock, kThreading, kImplemented); // NOTE: This function is very commonly inlined, and probably won't be called! -pointer_result_t InterlockedPushEntrySList( +pointer_result_t InterlockedPushEntrySList_entry( pointer_t plist_ptr, pointer_t entry) { assert_not_null(plist_ptr); assert_not_null(entry); @@ -1253,7 +1334,8 @@ pointer_result_t InterlockedPushEntrySList( DECLARE_XBOXKRNL_EXPORT2(InterlockedPushEntrySList, kThreading, kImplemented, kHighFrequency); -pointer_result_t InterlockedPopEntrySList(pointer_t plist_ptr) { +pointer_result_t InterlockedPopEntrySList_entry( + pointer_t plist_ptr) { assert_not_null(plist_ptr); uint32_t popped = 0; @@ -1280,7 +1362,8 @@ pointer_result_t InterlockedPopEntrySList(pointer_t plist_ptr) { DECLARE_XBOXKRNL_EXPORT2(InterlockedPopEntrySList, kThreading, kImplemented, kHighFrequency); -pointer_result_t InterlockedFlushSList(pointer_t plist_ptr) { +pointer_result_t InterlockedFlushSList_entry( + pointer_t plist_ptr) { assert_not_null(plist_ptr); alignas(8) X_SLIST_HEADER old_hdr = *plist_ptr; @@ -1300,9 +1383,8 @@ pointer_result_t InterlockedFlushSList(pointer_t plist_ptr) { } DECLARE_XBOXKRNL_EXPORT1(InterlockedFlushSList, kThreading, kImplemented); -void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Threading); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_usbcam.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_usbcam.cc index 40c3f1987..2fc29e5ed 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_usbcam.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_usbcam.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,9 +17,9 @@ namespace xe { namespace kernel { namespace xboxkrnl { -dword_result_t XUsbcamCreate(dword_t buffer, - dword_t buffer_size, // 0x4B000 640x480? - lpunknown_t unk3_ptr) { +dword_result_t XUsbcamCreate_entry(dword_t buffer, + dword_t buffer_size, // 0x4B000 640x480? + lpunknown_t unk3_ptr) { // This function should return success. // It looks like it only allocates space for usbcam support. // returning error code might cause games to initialize incorrectly. @@ -31,15 +31,14 @@ dword_result_t XUsbcamCreate(dword_t buffer, } DECLARE_XBOXKRNL_EXPORT1(XUsbcamCreate, kNone, kStub); -dword_result_t XUsbcamGetState() { +dword_result_t XUsbcamGetState_entry() { // 0 = not connected. return 0; } DECLARE_XBOXKRNL_EXPORT1(XUsbcamGetState, kNone, kStub); -void RegisterUsbcamExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Usbcam); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc index e05415570..8ebacd35b 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -48,7 +48,7 @@ namespace xboxkrnl { // https://www.microsoft.com/en-za/download/details.aspx?id=5313 -- "Stripped // Down Direct3D: Xbox 360 Command Buffer and Resource Management" -void VdGetCurrentDisplayGamma(lpdword_t type_ptr, lpfloat_t power_ptr) { +void VdGetCurrentDisplayGamma_entry(lpdword_t type_ptr, lpfloat_t power_ptr) { // 1 - sRGB. // 2 - TV (BT.709). // 3 - use the power written to *power_ptr. @@ -104,9 +104,8 @@ struct X_DISPLAY_INFO { }; static_assert_size(X_DISPLAY_INFO, 0x58); -void VdQueryVideoMode(pointer_t video_mode); - -void VdGetCurrentDisplayInformation(pointer_t display_info) { +void VdGetCurrentDisplayInformation_entry( + pointer_t display_info) { X_VIDEO_MODE mode; VdQueryVideoMode(&mode); @@ -132,9 +131,9 @@ void VdGetCurrentDisplayInformation(pointer_t display_info) { } DECLARE_XBOXKRNL_EXPORT1(VdGetCurrentDisplayInformation, kVideo, kStub); -void VdQueryVideoMode(pointer_t video_mode) { +void VdQueryVideoMode(X_VIDEO_MODE* video_mode) { // TODO(benvanik): get info from actual display. - video_mode.Zero(); + std::memset(video_mode, 0, sizeof(X_VIDEO_MODE)); video_mode->display_width = 1280; video_mode->display_height = 720; video_mode->is_interlaced = 0; @@ -145,9 +144,13 @@ void VdQueryVideoMode(pointer_t video_mode) { video_mode->unknown_0x8a = 0x4A; video_mode->unknown_0x01 = 0x01; } + +void VdQueryVideoMode_entry(pointer_t video_mode) { + VdQueryVideoMode(video_mode); +} DECLARE_XBOXKRNL_EXPORT1(VdQueryVideoMode, kVideo, kStub); -dword_result_t VdQueryVideoFlags() { +dword_result_t VdQueryVideoFlags_entry() { X_VIDEO_MODE mode; VdQueryVideoMode(&mode); @@ -160,7 +163,7 @@ dword_result_t VdQueryVideoFlags() { } DECLARE_XBOXKRNL_EXPORT1(VdQueryVideoFlags, kVideo, kStub); -dword_result_t VdSetDisplayMode(dword_t flags) { +dword_result_t VdSetDisplayMode_entry(dword_t flags) { // Often 0x40000000. // 0?ccf000 00000000 00000000 000000r0 @@ -179,17 +182,17 @@ dword_result_t VdSetDisplayMode(dword_t flags) { } DECLARE_XBOXKRNL_EXPORT1(VdSetDisplayMode, kVideo, kStub); -dword_result_t VdSetDisplayModeOverride(unknown_t unk0, unknown_t unk1, - double_t refresh_rate, unknown_t unk3, - unknown_t unk4) { +dword_result_t VdSetDisplayModeOverride_entry(unknown_t unk0, unknown_t unk1, + double_t refresh_rate, + unknown_t unk3, unknown_t unk4) { // refresh_rate = 0, 50, 59.9, etc. return 0; } DECLARE_XBOXKRNL_EXPORT1(VdSetDisplayModeOverride, kVideo, kStub); -dword_result_t VdInitializeEngines(unknown_t unk0, function_t callback, - lpvoid_t arg, lpdword_t pfp_ptr, - lpdword_t me_ptr) { +dword_result_t VdInitializeEngines_entry(unknown_t unk0, function_t callback, + lpvoid_t arg, lpdword_t pfp_ptr, + lpdword_t me_ptr) { // r3 = 0x4F810000 // r4 = function ptr (cleanup callback?) // r5 = function arg @@ -199,27 +202,28 @@ dword_result_t VdInitializeEngines(unknown_t unk0, function_t callback, } DECLARE_XBOXKRNL_EXPORT1(VdInitializeEngines, kVideo, kStub); -void VdShutdownEngines() { +void VdShutdownEngines_entry() { // Ignored for now. // Games seem to call an Initialize/Shutdown pair to query info, then // re-initialize. } DECLARE_XBOXKRNL_EXPORT1(VdShutdownEngines, kVideo, kStub); -dword_result_t VdGetGraphicsAsicID() { +dword_result_t VdGetGraphicsAsicID_entry() { // Games compare for < 0x10 and do VdInitializeEDRAM, else other // (retrain/etc). return 0x11; } DECLARE_XBOXKRNL_EXPORT1(VdGetGraphicsAsicID, kVideo, kStub); -dword_result_t VdEnableDisableClockGating(dword_t enabled) { +dword_result_t VdEnableDisableClockGating_entry(dword_t enabled) { // Ignored, as it really doesn't matter. return 0; } DECLARE_XBOXKRNL_EXPORT1(VdEnableDisableClockGating, kVideo, kStub); -void VdSetGraphicsInterruptCallback(function_t callback, lpvoid_t user_data) { +void VdSetGraphicsInterruptCallback_entry(function_t callback, + lpvoid_t user_data) { // callback takes 2 params // r3 = bool 0/1 - 0 is normal interrupt, 1 is some acquire/lock mumble // r4 = user_data (r4 of VdSetGraphicsInterruptCallback) @@ -228,7 +232,7 @@ void VdSetGraphicsInterruptCallback(function_t callback, lpvoid_t user_data) { } DECLARE_XBOXKRNL_EXPORT1(VdSetGraphicsInterruptCallback, kVideo, kImplemented); -void VdInitializeRingBuffer(lpvoid_t ptr, int_t size_log2) { +void VdInitializeRingBuffer_entry(lpvoid_t ptr, int_t size_log2) { // r3 = result of MmGetPhysicalAddress // r4 = log2(size) // Buffer pointers are from MmAllocatePhysicalMemory with WRITE_COMBINE. @@ -237,21 +241,22 @@ void VdInitializeRingBuffer(lpvoid_t ptr, int_t size_log2) { } DECLARE_XBOXKRNL_EXPORT1(VdInitializeRingBuffer, kVideo, kImplemented); -void VdEnableRingBufferRPtrWriteBack(lpvoid_t ptr, int_t block_size_log2) { +void VdEnableRingBufferRPtrWriteBack_entry(lpvoid_t ptr, + int_t block_size_log2) { // r4 = log2(block size), 6, usually --- <=19 auto graphics_system = kernel_state()->emulator()->graphics_system(); graphics_system->EnableReadPointerWriteBack(ptr, block_size_log2); } DECLARE_XBOXKRNL_EXPORT1(VdEnableRingBufferRPtrWriteBack, kVideo, kImplemented); -void VdGetSystemCommandBuffer(lpunknown_t p0_ptr, lpunknown_t p1_ptr) { +void VdGetSystemCommandBuffer_entry(lpunknown_t p0_ptr, lpunknown_t p1_ptr) { p0_ptr.Zero(0x94); xe::store_and_swap(p0_ptr, 0xBEEF0000); xe::store_and_swap(p1_ptr, 0xBEEF0001); } DECLARE_XBOXKRNL_EXPORT1(VdGetSystemCommandBuffer, kVideo, kStub); -void VdSetSystemCommandBufferGpuIdentifierAddress(lpunknown_t unk) { +void VdSetSystemCommandBufferGpuIdentifierAddress_entry(lpunknown_t unk) { // r3 = 0x2B10(d3d?) + 8 } DECLARE_XBOXKRNL_EXPORT1(VdSetSystemCommandBufferGpuIdentifierAddress, kVideo, @@ -262,7 +267,7 @@ DECLARE_XBOXKRNL_EXPORT1(VdSetSystemCommandBufferGpuIdentifierAddress, kVideo, // r4 = 19 // no op? -dword_result_t VdInitializeScalerCommandBuffer( +dword_result_t VdInitializeScalerCommandBuffer_entry( dword_t scaler_source_xy, // ((uint16_t)y << 16) | (uint16_t)x dword_t scaler_source_wh, // ((uint16_t)h << 16) | (uint16_t)w dword_t scaled_output_xy, // ((uint16_t)y << 16) | (uint16_t)x @@ -302,7 +307,7 @@ void AppendParam(StringBuffer* string_buffer, pointer_t param) { uint16_t(param->fb_width), uint16_t(param->fb_height)); } -dword_result_t VdCallGraphicsNotificationRoutines( +dword_result_t VdCallGraphicsNotificationRoutines_entry( unknown_t unk0, pointer_t args_ptr) { assert_true(unk0 == 1); @@ -313,13 +318,13 @@ dword_result_t VdCallGraphicsNotificationRoutines( DECLARE_XBOXKRNL_EXPORT2(VdCallGraphicsNotificationRoutines, kVideo, kImplemented, kSketchy); -dword_result_t VdIsHSIOTrainingSucceeded() { +dword_result_t VdIsHSIOTrainingSucceeded_entry() { // BOOL return value return 1; } DECLARE_XBOXKRNL_EXPORT1(VdIsHSIOTrainingSucceeded, kVideo, kStub); -dword_result_t VdPersistDisplay(unknown_t unk0, lpdword_t unk1_ptr) { +dword_result_t VdPersistDisplay_entry(unknown_t unk0, lpdword_t unk1_ptr) { // unk1_ptr needs to be populated with a pointer passed to // MmFreePhysicalMemory(1, *unk1_ptr). if (unk1_ptr) { @@ -334,23 +339,25 @@ dword_result_t VdPersistDisplay(unknown_t unk0, lpdword_t unk1_ptr) { } DECLARE_XBOXKRNL_EXPORT2(VdPersistDisplay, kVideo, kImplemented, kSketchy); -dword_result_t VdRetrainEDRAMWorker(unknown_t unk0) { return 0; } +dword_result_t VdRetrainEDRAMWorker_entry(unknown_t unk0) { return 0; } DECLARE_XBOXKRNL_EXPORT1(VdRetrainEDRAMWorker, kVideo, kStub); -dword_result_t VdRetrainEDRAM(unknown_t unk0, unknown_t unk1, unknown_t unk2, - unknown_t unk3, unknown_t unk4, unknown_t unk5) { +dword_result_t VdRetrainEDRAM_entry(unknown_t unk0, unknown_t unk1, + unknown_t unk2, unknown_t unk3, + unknown_t unk4, unknown_t unk5) { return 0; } DECLARE_XBOXKRNL_EXPORT1(VdRetrainEDRAM, kVideo, kStub); -void VdSwap(lpvoid_t buffer_ptr, // ptr into primary ringbuffer - lpvoid_t fetch_ptr, // frontbuffer Direct3D 9 texture header fetch - lpunknown_t unk2, // system writeback ptr - lpunknown_t unk3, // buffer from VdGetSystemCommandBuffer - lpunknown_t unk4, // from VdGetSystemCommandBuffer (0xBEEF0001) - lpdword_t frontbuffer_ptr, // ptr to frontbuffer address - lpdword_t texture_format_ptr, lpdword_t color_space_ptr, - lpdword_t width, lpdword_t height) { +void VdSwap_entry( + lpvoid_t buffer_ptr, // ptr into primary ringbuffer + lpvoid_t fetch_ptr, // frontbuffer Direct3D 9 texture header fetch + lpunknown_t unk2, // system writeback ptr + lpunknown_t unk3, // buffer from VdGetSystemCommandBuffer + lpunknown_t unk4, // from VdGetSystemCommandBuffer (0xBEEF0001) + lpdword_t frontbuffer_ptr, // ptr to frontbuffer address + lpdword_t texture_format_ptr, lpdword_t color_space_ptr, lpdword_t width, + lpdword_t height) { // All of these parameters are REQUIRED. assert(buffer_ptr); assert(fetch_ptr); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_video.h b/src/xenia/kernel/xboxkrnl/xboxkrnl_video.h index 2d26c6bd3..4cb3861f4 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_video.h +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_video.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,7 +17,7 @@ namespace xe { namespace kernel { namespace xboxkrnl { -void VdQueryVideoMode(pointer_t video_mode); +void VdQueryVideoMode(X_VIDEO_MODE* video_mode); } // namespace xboxkrnl } // namespace kernel diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_xconfig.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_xconfig.cc index f6b0b09bd..8c8b009c7 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_xconfig.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_xconfig.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2019 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -122,9 +122,10 @@ X_STATUS xeExGetXConfigSetting(uint16_t category, uint16_t setting, return X_STATUS_SUCCESS; } -dword_result_t ExGetXConfigSetting(word_t category, word_t setting, - lpdword_t buffer_ptr, word_t buffer_size, - lpword_t required_size_ptr) { +dword_result_t ExGetXConfigSetting_entry(word_t category, word_t setting, + lpvoid_t buffer_ptr, + word_t buffer_size, + lpword_t required_size_ptr) { uint16_t required_size = 0; X_STATUS result = xeExGetXConfigSetting(category, setting, buffer_ptr, buffer_size, &required_size); @@ -137,9 +138,8 @@ dword_result_t ExGetXConfigSetting(word_t category, word_t setting, } DECLARE_XBOXKRNL_EXPORT1(ExGetXConfigSetting, kModules, kImplemented); -void RegisterXConfigExports(xe::cpu::ExportResolver* export_resolver, - KernelState* kernel_state) {} - } // namespace xboxkrnl } // namespace kernel } // namespace xe + +DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(XConfig); diff --git a/src/xenia/kernel/xthread.cc b/src/xenia/kernel/xthread.cc index 43303c04e..9c269c6b7 100644 --- a/src/xenia/kernel/xthread.cc +++ b/src/xenia/kernel/xthread.cc @@ -14,6 +14,7 @@ #include "third_party/fmt/include/fmt/format.h" #include "xenia/base/byte_stream.h" #include "xenia/base/clock.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/profiling.h" @@ -41,6 +42,8 @@ const uint32_t XAPC::kDummyRundownRoutine; using xe::cpu::ppc::PPCOpcode; +using namespace xe::literals; + uint32_t next_xthread_id_ = 0; XThread::XThread(KernelState* kernel_state) @@ -370,7 +373,7 @@ X_STATUS XThread::Create() { RetainHandle(); xe::threading::Thread::CreationParameters params; - params.stack_size = 16 * 1024 * 1024; // Allocate a big host stack. + params.stack_size = 16_MiB; // Allocate a big host stack. params.create_suspended = true; thread_ = xe::threading::Thread::Create(params, [this]() { // Set thread ID override. This is used by logging. @@ -1018,7 +1021,7 @@ object_ref XThread::Restore(KernelState* kernel_state, xe::threading::Thread::CreationParameters params; params.create_suspended = true; // Not done restoring yet. - params.stack_size = 16 * 1024 * 1024; + params.stack_size = 16_MiB; thread->thread_ = xe::threading::Thread::Create(params, [thread, state]() { // Set thread ID override. This is used by logging. xe::threading::set_current_thread_id(thread->handle()); diff --git a/src/xenia/ui/d3d12/d3d12_api.h b/src/xenia/ui/d3d12/d3d12_api.h index e474d9391..82bc44bff 100644 --- a/src/xenia/ui/d3d12/d3d12_api.h +++ b/src/xenia/ui/d3d12/d3d12_api.h @@ -10,15 +10,14 @@ #ifndef XENIA_UI_D3D12_D3D12_API_H_ #define XENIA_UI_D3D12_D3D12_API_H_ -// This must be included before D3D and DXGI for things like NOMINMAX. +// Must be included before D3D and DXGI for things like NOMINMAX. #include "xenia/base/platform_win.h" #include #include #include #include -#include -#include +#include #include // For Microsoft::WRL::ComPtr. #include diff --git a/src/xenia/ui/d3d12/d3d12_context.cc b/src/xenia/ui/d3d12/d3d12_context.cc deleted file mode 100644 index a37c61b72..000000000 --- a/src/xenia/ui/d3d12/d3d12_context.cc +++ /dev/null @@ -1,379 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/d3d12/d3d12_context.h" - -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/ui/d3d12/d3d12_immediate_drawer.h" -#include "xenia/ui/d3d12/d3d12_provider.h" -#include "xenia/ui/d3d12/d3d12_util.h" -#include "xenia/ui/window.h" - -namespace xe { -namespace ui { -namespace d3d12 { - -D3D12Context::D3D12Context(D3D12Provider* provider, Window* target_window) - : GraphicsContext(provider, target_window) {} - -D3D12Context::~D3D12Context() { Shutdown(); } - -bool D3D12Context::Initialize() { - context_lost_ = false; - - if (!target_window_) { - return true; - } - - const D3D12Provider& provider = GetD3D12Provider(); - IDXGIFactory2* dxgi_factory = provider.GetDXGIFactory(); - ID3D12Device* device = provider.GetDevice(); - ID3D12CommandQueue* direct_queue = provider.GetDirectQueue(); - - swap_fence_current_value_ = 1; - swap_fence_completed_value_ = 0; - swap_fence_completion_event_ = CreateEvent(nullptr, false, false, nullptr); - if (swap_fence_completion_event_ == nullptr) { - XELOGE("Failed to create the composition fence completion event"); - Shutdown(); - return false; - } - // Create a fence for transient resources of compositing. - if (FAILED(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, - IID_PPV_ARGS(&swap_fence_)))) { - XELOGE("Failed to create the composition fence"); - Shutdown(); - return false; - } - - // Create the swap chain. - swap_chain_width_ = target_window_->scaled_width(); - swap_chain_height_ = target_window_->scaled_height(); - DXGI_SWAP_CHAIN_DESC1 swap_chain_desc; - swap_chain_desc.Width = swap_chain_width_; - swap_chain_desc.Height = swap_chain_height_; - swap_chain_desc.Format = kSwapChainFormat; - swap_chain_desc.Stereo = FALSE; - swap_chain_desc.SampleDesc.Count = 1; - swap_chain_desc.SampleDesc.Quality = 0; - swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swap_chain_desc.BufferCount = kSwapChainBufferCount; - swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; - swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; - swap_chain_desc.Flags = 0; - IDXGISwapChain1* swap_chain_1; - if (FAILED(dxgi_factory->CreateSwapChainForComposition( - provider.GetDirectQueue(), &swap_chain_desc, nullptr, - &swap_chain_1))) { - XELOGE("Failed to create a DXGI swap chain for composition"); - Shutdown(); - return false; - } - if (FAILED(swap_chain_1->QueryInterface(IID_PPV_ARGS(&swap_chain_)))) { - XELOGE("Failed to get version 3 of the DXGI swap chain interface"); - swap_chain_1->Release(); - Shutdown(); - return false; - } - swap_chain_1->Release(); - - // Create a heap for RTV descriptors of swap chain buffers. - D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc; - rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - rtv_heap_desc.NumDescriptors = kSwapChainBufferCount; - rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - rtv_heap_desc.NodeMask = 0; - if (FAILED(device->CreateDescriptorHeap( - &rtv_heap_desc, IID_PPV_ARGS(&swap_chain_rtv_heap_)))) { - XELOGE("Failed to create swap chain RTV descriptor heap"); - Shutdown(); - return false; - } - swap_chain_rtv_heap_start_ = - swap_chain_rtv_heap_->GetCPUDescriptorHandleForHeapStart(); - - // Get the buffers and create their RTV descriptors. - if (!InitializeSwapChainBuffers()) { - Shutdown(); - return false; - } - - // Create the command list for compositing. - for (uint32_t i = 0; i < kSwapCommandAllocatorCount; ++i) { - if (FAILED(device->CreateCommandAllocator( - D3D12_COMMAND_LIST_TYPE_DIRECT, - IID_PPV_ARGS(&swap_command_allocators_[i])))) { - XELOGE("Failed to create a composition command allocator"); - Shutdown(); - return false; - } - } - if (FAILED(device->CreateCommandList( - 0, D3D12_COMMAND_LIST_TYPE_DIRECT, swap_command_allocators_[0].Get(), - nullptr, IID_PPV_ARGS(&swap_command_list_)))) { - XELOGE("Failed to create the composition graphics command list"); - Shutdown(); - return false; - } - // Initially in open state, wait until BeginSwap. - swap_command_list_->Close(); - - // Associate the swap chain with the window via DirectComposition. - if (FAILED(provider.CreateDCompositionDevice(nullptr, - IID_PPV_ARGS(&dcomp_device_)))) { - XELOGE("Failed to create a DirectComposition device"); - Shutdown(); - return false; - } - if (FAILED(dcomp_device_->CreateTargetForHwnd( - reinterpret_cast(target_window_->native_handle()), TRUE, - &dcomp_target_))) { - XELOGE("Failed to create a DirectComposition target for the window"); - Shutdown(); - return false; - } - if (FAILED(dcomp_device_->CreateVisual(&dcomp_visual_))) { - XELOGE("Failed to create a DirectComposition visual"); - Shutdown(); - return false; - } - if (FAILED(dcomp_visual_->SetContent(swap_chain_.Get()))) { - XELOGE( - "Failed to set the content of the DirectComposition visual to the swap " - "chain"); - Shutdown(); - return false; - } - if (FAILED(dcomp_target_->SetRoot(dcomp_visual_.Get()))) { - XELOGE( - "Failed to set the root of the DirectComposition target to the swap " - "chain visual"); - Shutdown(); - return false; - } - if (FAILED(dcomp_device_->Commit())) { - XELOGE("Failed to commit DirectComposition commands"); - Shutdown(); - return false; - } - - // Initialize the immediate mode drawer if not offscreen. - immediate_drawer_ = std::make_unique(*this); - if (!immediate_drawer_->Initialize()) { - Shutdown(); - return false; - } - - return true; -} - -bool D3D12Context::InitializeSwapChainBuffers() { - // Get references to the buffers. - for (uint32_t i = 0; i < kSwapChainBufferCount; ++i) { - if (FAILED( - swap_chain_->GetBuffer(i, IID_PPV_ARGS(&swap_chain_buffers_[i])))) { - XELOGE("Failed to get buffer {} of the swap chain", i); - return false; - } - } - - // Get the back buffer index for the first draw. - swap_chain_back_buffer_index_ = swap_chain_->GetCurrentBackBufferIndex(); - - // Create RTV descriptors for the swap chain buffers. - ID3D12Device* device = GetD3D12Provider().GetDevice(); - D3D12_RENDER_TARGET_VIEW_DESC rtv_desc; - rtv_desc.Format = kSwapChainFormat; - rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - rtv_desc.Texture2D.MipSlice = 0; - rtv_desc.Texture2D.PlaneSlice = 0; - for (uint32_t i = 0; i < kSwapChainBufferCount; ++i) { - device->CreateRenderTargetView(swap_chain_buffers_[i].Get(), &rtv_desc, - GetSwapChainBufferRTV(i)); - } - - return true; -} - -void D3D12Context::Shutdown() { - if (!target_window_) { - return; - } - - if (!context_lost_ && swap_fence_ && - swap_fence_->GetCompletedValue() + 1 < swap_fence_current_value_) { - swap_fence_->SetEventOnCompletion(swap_fence_current_value_ - 1, - swap_fence_completion_event_); - WaitForSingleObject(swap_fence_completion_event_, INFINITE); - } - - immediate_drawer_.reset(); - - dcomp_visual_.Reset(); - dcomp_target_.Reset(); - dcomp_device_.Reset(); - - swap_command_list_.Reset(); - for (uint32_t i = 0; i < kSwapCommandAllocatorCount; ++i) { - swap_command_allocators_[i].Reset(); - } - - for (uint32_t i = 0; i < kSwapChainBufferCount; ++i) { - swap_chain_buffers_[i].Reset(); - } - swap_chain_rtv_heap_.Reset(); - swap_chain_.Reset(); - - // First release the fence since it may reference the event. - swap_fence_.Reset(); - if (swap_fence_completion_event_) { - CloseHandle(swap_fence_completion_event_); - swap_fence_completion_event_ = nullptr; - } - swap_fence_current_value_ = 1; - swap_fence_completed_value_ = 0; -} - -ImmediateDrawer* D3D12Context::immediate_drawer() { - return immediate_drawer_.get(); -} - -bool D3D12Context::WasLost() { return context_lost_; } - -bool D3D12Context::BeginSwap() { - if (!target_window_ || context_lost_) { - return false; - } - - // Resize the swap chain if the window is resized. - uint32_t target_window_width = target_window_->scaled_width(); - uint32_t target_window_height = target_window_->scaled_height(); - if (swap_chain_width_ != target_window_width || - swap_chain_height_ != target_window_height) { - // Await the completion of swap chain use. - // Context loss is also faked if resizing fails. In this case, before the - // context is shut down to be recreated, frame completion must be awaited - // (this isn't done if the context is truly lost). - if (swap_fence_completed_value_ + 1 < swap_fence_current_value_) { - swap_fence_->SetEventOnCompletion(swap_fence_current_value_ - 1, - swap_fence_completion_event_); - WaitForSingleObject(swap_fence_completion_event_, INFINITE); - swap_fence_completed_value_ = swap_fence_current_value_ - 1; - } - // All buffer references must be released before resizing. - for (uint32_t i = 0; i < kSwapChainBufferCount; ++i) { - swap_chain_buffers_[i].Reset(); - } - if (FAILED(swap_chain_->ResizeBuffers( - kSwapChainBufferCount, target_window_width, target_window_height, - kSwapChainFormat, 0))) { - context_lost_ = true; - return false; - } - swap_chain_width_ = target_window_width; - swap_chain_height_ = target_window_height; - if (!InitializeSwapChainBuffers()) { - context_lost_ = true; - return false; - } - } - - // Wait for a swap command allocator to become free. - // Command allocator 0 is used when swap_fence_current_value_ is 1, 4, 7... - swap_fence_completed_value_ = swap_fence_->GetCompletedValue(); - if (swap_fence_completed_value_ + kSwapCommandAllocatorCount < - swap_fence_current_value_) { - swap_fence_->SetEventOnCompletion( - swap_fence_current_value_ - kSwapCommandAllocatorCount, - swap_fence_completion_event_); - WaitForSingleObject(swap_fence_completion_event_, INFINITE); - swap_fence_completed_value_ = swap_fence_->GetCompletedValue(); - } - - // Start the command list. - uint32_t command_allocator_index = - uint32_t((swap_fence_current_value_ + (kSwapCommandAllocatorCount - 1)) % - kSwapCommandAllocatorCount); - ID3D12CommandAllocator* command_allocator = - swap_command_allocators_[command_allocator_index].Get(); - command_allocator->Reset(); - swap_command_list_->Reset(command_allocator, nullptr); - - // Bind the back buffer as a render target and clear it. - D3D12_RESOURCE_BARRIER barrier; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = - swap_chain_buffers_[swap_chain_back_buffer_index_].Get(); - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; - swap_command_list_->ResourceBarrier(1, &barrier); - D3D12_CPU_DESCRIPTOR_HANDLE back_buffer_rtv = GetSwapChainBackBufferRTV(); - swap_command_list_->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr); - float clear_color[4]; - GetClearColor(clear_color); - swap_command_list_->ClearRenderTargetView(back_buffer_rtv, clear_color, 0, - nullptr); - - return true; -} - -void D3D12Context::EndSwap() { - if (!target_window_ || context_lost_) { - return; - } - - ID3D12CommandQueue* direct_queue = GetD3D12Provider().GetDirectQueue(); - - // Switch the back buffer to presentation state. - D3D12_RESOURCE_BARRIER barrier; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = - swap_chain_buffers_[swap_chain_back_buffer_index_].Get(); - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; - swap_command_list_->ResourceBarrier(1, &barrier); - - // Submit the command list. - swap_command_list_->Close(); - ID3D12CommandList* execute_command_lists[] = {swap_command_list_.Get()}; - direct_queue->ExecuteCommandLists(1, execute_command_lists); - - // Present and check if the context was lost. - if (FAILED(swap_chain_->Present(0, 0))) { - context_lost_ = true; - return; - } - - // Signal the fence to wait for frame resources to become free again. - direct_queue->Signal(swap_fence_.Get(), swap_fence_current_value_++); - - // Get the back buffer index for the next frame. - swap_chain_back_buffer_index_ = swap_chain_->GetCurrentBackBufferIndex(); -} - -std::unique_ptr D3D12Context::Capture() { - // TODO(Triang3l): Read back swap chain front buffer. - return nullptr; -} - -D3D12_CPU_DESCRIPTOR_HANDLE D3D12Context::GetSwapChainBufferRTV( - uint32_t buffer_index) const { - return GetD3D12Provider().OffsetRTVDescriptor(swap_chain_rtv_heap_start_, - buffer_index); -} - -} // namespace d3d12 -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/d3d12/d3d12_context.h b/src/xenia/ui/d3d12/d3d12_context.h deleted file mode 100644 index 308d3aa6f..000000000 --- a/src/xenia/ui/d3d12/d3d12_context.h +++ /dev/null @@ -1,112 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_D3D12_D3D12_CONTEXT_H_ -#define XENIA_UI_D3D12_D3D12_CONTEXT_H_ - -#include - -#include "xenia/ui/d3d12/d3d12_immediate_drawer.h" -#include "xenia/ui/d3d12/d3d12_provider.h" -#include "xenia/ui/graphics_context.h" - -namespace xe { -namespace ui { -namespace d3d12 { - -class D3D12Context : public GraphicsContext { - public: - ~D3D12Context() override; - - ImmediateDrawer* immediate_drawer() override; - - bool WasLost() override; - - bool BeginSwap() override; - void EndSwap() override; - - std::unique_ptr Capture() override; - - D3D12Provider& GetD3D12Provider() const { - return static_cast(*provider_); - } - - // The format used by DWM. - static constexpr DXGI_FORMAT kSwapChainFormat = DXGI_FORMAT_B8G8R8A8_UNORM; - ID3D12Resource* GetSwapChainBuffer(uint32_t buffer_index) const { - return swap_chain_buffers_[buffer_index].Get(); - } - uint32_t GetSwapChainBackBufferIndex() const { - return swap_chain_back_buffer_index_; - } - D3D12_CPU_DESCRIPTOR_HANDLE GetSwapChainBufferRTV( - uint32_t buffer_index) const; - D3D12_CPU_DESCRIPTOR_HANDLE GetSwapChainBackBufferRTV() const { - return GetSwapChainBufferRTV(GetSwapChainBackBufferIndex()); - } - void GetSwapChainSize(uint32_t& width, uint32_t& height) const { - width = swap_chain_width_; - height = swap_chain_height_; - } - // Inside the current BeginSwap/EndSwap pair. - uint64_t GetSwapCurrentFenceValue() const { - return swap_fence_current_value_; - } - uint64_t GetSwapCompletedFenceValue() const { - return swap_fence_completed_value_; - } - ID3D12GraphicsCommandList* GetSwapCommandList() const { - return swap_command_list_.Get(); - } - - private: - friend class D3D12Provider; - explicit D3D12Context(D3D12Provider* provider, Window* target_window); - bool Initialize(); - - private: - bool InitializeSwapChainBuffers(); - void Shutdown(); - - bool context_lost_ = false; - - static constexpr uint32_t kSwapChainBufferCount = 3; - Microsoft::WRL::ComPtr swap_chain_; - uint32_t swap_chain_width_ = 0, swap_chain_height_ = 0; - Microsoft::WRL::ComPtr - swap_chain_buffers_[kSwapChainBufferCount]; - uint32_t swap_chain_back_buffer_index_ = 0; - Microsoft::WRL::ComPtr swap_chain_rtv_heap_; - D3D12_CPU_DESCRIPTOR_HANDLE swap_chain_rtv_heap_start_; - - uint64_t swap_fence_current_value_ = 1; - uint64_t swap_fence_completed_value_ = 0; - HANDLE swap_fence_completion_event_ = nullptr; - Microsoft::WRL::ComPtr swap_fence_; - - static constexpr uint32_t kSwapCommandAllocatorCount = 3; - Microsoft::WRL::ComPtr - swap_command_allocators_[kSwapCommandAllocatorCount]; - // Current command allocator is: - // ((swap_fence_current_value_ + (kSwapCommandAllocatorCount - 1))) % - // kSwapCommandAllocatorCount. - Microsoft::WRL::ComPtr swap_command_list_; - - Microsoft::WRL::ComPtr dcomp_device_; - Microsoft::WRL::ComPtr dcomp_target_; - Microsoft::WRL::ComPtr dcomp_visual_; - - std::unique_ptr immediate_drawer_; -}; - -} // namespace d3d12 -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_D3D12_D3D12_CONTEXT_H_ diff --git a/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.cc b/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.cc index 5d3dac99d..906a8a1d9 100644 --- a/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.cc +++ b/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -41,6 +41,25 @@ void D3D12DescriptorHeapPool::Reclaim(uint64_t completed_submission_index) { } } +void D3D12DescriptorHeapPool::ChangeSubmissionTimeline() { + // Reclaim all submitted pages. + if (writable_last_) { + writable_last_->next = submitted_first_; + } else { + writable_first_ = submitted_first_; + } + writable_last_ = submitted_last_; + submitted_first_ = nullptr; + submitted_last_ = nullptr; + + // Mark all pages as never used yet in the new timeline. + Page* page = writable_first_; + while (page) { + page->last_submission_index = 0; + page = page->next; + } +} + void D3D12DescriptorHeapPool::ClearCache() { // Not checking current_page_used_ != 0 because asking for 0 descriptors // returns a valid heap also - but actually the new heap will be different now @@ -49,14 +68,12 @@ void D3D12DescriptorHeapPool::ClearCache() { current_page_used_ = 0; while (submitted_first_) { auto next = submitted_first_->next; - submitted_first_->heap->Release(); delete submitted_first_; submitted_first_ = next; } submitted_last_ = nullptr; while (writable_first_) { auto next = writable_first_->next; - writable_first_->heap->Release(); delete writable_first_; writable_first_ = next; } @@ -110,7 +127,7 @@ uint64_t D3D12DescriptorHeapPool::Request(uint64_t submission_index, new_heap_desc.NumDescriptors = page_size_; new_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; new_heap_desc.NodeMask = 0; - ID3D12DescriptorHeap* new_heap; + Microsoft::WRL::ComPtr new_heap; if (FAILED(device_->CreateDescriptorHeap(&new_heap_desc, IID_PPV_ARGS(&new_heap)))) { XELOGE("Failed to create a heap for {} shader-visible descriptors", diff --git a/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.h b/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.h index fbc77aeef..9eb1c5b31 100644 --- a/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.h +++ b/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -30,6 +30,7 @@ class D3D12DescriptorHeapPool { ~D3D12DescriptorHeapPool(); void Reclaim(uint64_t completed_submission_index); + void ChangeSubmissionTimeline(); void ClearCache(); // Because all descriptors for a single draw call must be in the same heap, @@ -65,7 +66,7 @@ class D3D12DescriptorHeapPool { // after a successful request because before a request, the heap may not exist // yet. ID3D12DescriptorHeap* GetLastRequestHeap() const { - return writable_first_->heap; + return writable_first_->heap.Get(); } D3D12_CPU_DESCRIPTOR_HANDLE GetLastRequestHeapCPUStart() const { return writable_first_->cpu_start; @@ -80,7 +81,7 @@ class D3D12DescriptorHeapPool { uint32_t page_size_; struct Page { - ID3D12DescriptorHeap* heap; + Microsoft::WRL::ComPtr heap; D3D12_CPU_DESCRIPTOR_HANDLE cpu_start; D3D12_GPU_DESCRIPTOR_HANDLE gpu_start; uint64_t last_submission_index; diff --git a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc index 5cd6b551c..76bdcb5c0 100644 --- a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc +++ b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,7 +17,7 @@ #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" -#include "xenia/ui/d3d12/d3d12_context.h" +#include "xenia/ui/d3d12/d3d12_presenter.h" #include "xenia/ui/d3d12/d3d12_util.h" namespace xe { @@ -38,35 +38,40 @@ D3D12ImmediateDrawer::D3D12ImmediateTexture::D3D12ImmediateTexture( resource_(resource), sampler_index_(sampler_index), immediate_drawer_(immediate_drawer), - immediate_drawer_index_(immediate_drawer_index) { - if (resource_) { - resource_->AddRef(); - } -} + immediate_drawer_index_(immediate_drawer_index) {} D3D12ImmediateDrawer::D3D12ImmediateTexture::~D3D12ImmediateTexture() { if (immediate_drawer_) { immediate_drawer_->OnImmediateTextureDestroyed(*this); } - if (resource_) { - resource_->Release(); - } } -void D3D12ImmediateDrawer::D3D12ImmediateTexture::OnImmediateDrawerShutdown() { +void D3D12ImmediateDrawer::D3D12ImmediateTexture::OnImmediateDrawerDestroyed() { immediate_drawer_ = nullptr; // Lifetime is not managed anymore, so don't keep the resource either. - util::ReleaseAndNull(resource_); + resource_.Reset(); } -D3D12ImmediateDrawer::D3D12ImmediateDrawer(D3D12Context& graphics_context) - : ImmediateDrawer(&graphics_context), context_(graphics_context) {} +D3D12ImmediateDrawer::~D3D12ImmediateDrawer() { + // Await GPU usage completion of all draws and texture uploads (which happen + // before draws). + auto d3d12_presenter = static_cast(presenter()); + if (d3d12_presenter) { + d3d12_presenter->AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + } -D3D12ImmediateDrawer::~D3D12ImmediateDrawer() { Shutdown(); } + // Texture resources and descriptors are owned and tracked by the immediate + // drawer. Zombie texture objects are supported, but are meaningless. + assert_true(textures_.empty()); + for (D3D12ImmediateTexture* texture : textures_) { + texture->OnImmediateDrawerDestroyed(); + } + textures_.clear(); +} bool D3D12ImmediateDrawer::Initialize() { - const D3D12Provider& provider = context_.GetD3D12Provider(); - ID3D12Device* device = provider.GetDevice(); + ID3D12Device* device = provider_.GetDevice(); // Create the root signature. D3D12_ROOT_PARAMETER root_parameters[size_t(RootParameter::kCount)]; @@ -99,7 +104,7 @@ bool D3D12ImmediateDrawer::Initialize() { } { auto& root_parameter = - root_parameters[size_t(RootParameter::kViewportSizeInv)]; + root_parameters[size_t(RootParameter::kCoordinateSpaceSizeInv)]; root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; root_parameter.Constants.ShaderRegister = 0; root_parameter.Constants.RegisterSpace = 0; @@ -113,16 +118,16 @@ bool D3D12ImmediateDrawer::Initialize() { root_signature_desc.pStaticSamplers = nullptr; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - root_signature_ = util::CreateRootSignature(provider, root_signature_desc); - if (root_signature_ == nullptr) { - XELOGE("Failed to create the Direct3D 12 immediate drawer root signature"); - Shutdown(); + *(root_signature_.ReleaseAndGetAddressOf()) = + util::CreateRootSignature(provider_, root_signature_desc); + if (!root_signature_) { + XELOGE("D3D12ImmediateDrawer: Failed to create the root signature"); return false; } // Create the pipelines. D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeline_desc = {}; - pipeline_desc.pRootSignature = root_signature_; + pipeline_desc.pRootSignature = root_signature_.Get(); pipeline_desc.VS.pShaderBytecode = shaders::immediate_vs; pipeline_desc.VS.BytecodeLength = sizeof(shaders::immediate_vs); pipeline_desc.PS.pShaderBytecode = shaders::immediate_ps; @@ -133,13 +138,10 @@ bool D3D12ImmediateDrawer::Initialize() { pipeline_blend_desc.SrcBlend = D3D12_BLEND_SRC_ALPHA; pipeline_blend_desc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA; pipeline_blend_desc.BlendOp = D3D12_BLEND_OP_ADD; - // Don't change alpha (always 1). - pipeline_blend_desc.SrcBlendAlpha = D3D12_BLEND_ZERO; + pipeline_blend_desc.SrcBlendAlpha = D3D12_BLEND_ONE; pipeline_blend_desc.DestBlendAlpha = D3D12_BLEND_ONE; pipeline_blend_desc.BlendOpAlpha = D3D12_BLEND_OP_ADD; - pipeline_blend_desc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_RED | - D3D12_COLOR_WRITE_ENABLE_GREEN | - D3D12_COLOR_WRITE_ENABLE_BLUE; + pipeline_blend_desc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; pipeline_desc.SampleMask = UINT_MAX; pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; @@ -161,23 +163,17 @@ bool D3D12ImmediateDrawer::Initialize() { UINT(xe::countof(pipeline_input_elements)); pipeline_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; pipeline_desc.NumRenderTargets = 1; - pipeline_desc.RTVFormats[0] = D3D12Context::kSwapChainFormat; + pipeline_desc.RTVFormats[0] = D3D12Presenter::kSwapChainFormat; pipeline_desc.SampleDesc.Count = 1; if (FAILED(device->CreateGraphicsPipelineState( &pipeline_desc, IID_PPV_ARGS(&pipeline_triangle_)))) { - XELOGE( - "Failed to create the Direct3D 12 immediate drawer triangle pipeline " - "state"); - Shutdown(); + XELOGE("D3D12ImmediateDrawer: Failed to create the triangle pipeline"); return false; } pipeline_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; if (FAILED(device->CreateGraphicsPipelineState( &pipeline_desc, IID_PPV_ARGS(&pipeline_line_)))) { - XELOGE( - "Failed to create the Direct3D 12 immediate drawer line pipeline " - "state"); - Shutdown(); + XELOGE("D3D12ImmediateDrawer: Failed to create the line pipeline"); return false; } @@ -190,14 +186,12 @@ bool D3D12ImmediateDrawer::Initialize() { if (FAILED(device->CreateDescriptorHeap(&sampler_heap_desc, IID_PPV_ARGS(&sampler_heap_)))) { XELOGE( - "Failed to create the Direct3D 12 immediate drawer sampler descriptor " - "heap"); - Shutdown(); + "D3D12ImmediateDrawer: Failed to create the sampler descriptor heap"); return false; } sampler_heap_cpu_start_ = sampler_heap_->GetCPUDescriptorHandleForHeapStart(); sampler_heap_gpu_start_ = sampler_heap_->GetGPUDescriptorHandleForHeapStart(); - uint32_t sampler_size = provider.GetSamplerDescriptorSize(); + uint32_t sampler_size = provider_.GetSamplerDescriptorSize(); // Nearest neighbor, clamp. D3D12_SAMPLER_DESC sampler_desc = {}; sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; @@ -228,58 +222,22 @@ bool D3D12ImmediateDrawer::Initialize() { device->CreateSampler(&sampler_desc, sampler_handle); // Create pools for draws. - vertex_buffer_pool_ = std::make_unique(provider); + vertex_buffer_pool_ = std::make_unique(provider_); texture_descriptor_pool_ = std::make_unique( device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 2048); // Reset the current state. - current_command_list_ = nullptr; batch_open_ = false; return true; } -void D3D12ImmediateDrawer::Shutdown() { - for (auto& deleted_texture : textures_deleted_) { - deleted_texture.first->Release(); - } - textures_deleted_.clear(); - - for (auto& texture_upload : texture_uploads_submitted_) { - texture_upload.buffer->Release(); - texture_upload.texture->Release(); - } - texture_uploads_submitted_.clear(); - - for (auto& texture_upload : texture_uploads_pending_) { - texture_upload.buffer->Release(); - texture_upload.texture->Release(); - } - texture_uploads_pending_.clear(); - - for (D3D12ImmediateTexture* texture : textures_) { - texture->OnImmediateDrawerShutdown(); - } - textures_.clear(); - - texture_descriptor_pool_.reset(); - vertex_buffer_pool_.reset(); - - util::ReleaseAndNull(sampler_heap_); - - util::ReleaseAndNull(pipeline_line_); - util::ReleaseAndNull(pipeline_triangle_); - - util::ReleaseAndNull(root_signature_); -} - std::unique_ptr D3D12ImmediateDrawer::CreateTexture( uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool is_repeated, const uint8_t* data) { - const D3D12Provider& provider = context_.GetD3D12Provider(); - ID3D12Device* device = provider.GetDevice(); + ID3D12Device* device = provider_.GetDevice(); D3D12_HEAP_FLAGS heap_flag_create_not_zeroed = - provider.GetHeapFlagCreateNotZeroed(); + provider_.GetHeapFlagCreateNotZeroed(); D3D12_RESOURCE_DESC resource_desc; resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; @@ -293,8 +251,8 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( resource_desc.SampleDesc.Quality = 0; resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE; - ID3D12Resource* resource; - if (SUCCEEDED(provider.GetDevice()->CreateCommittedResource( + Microsoft::WRL::ComPtr resource; + if (SUCCEEDED(device->CreateCommittedResource( &util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, &resource_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&resource)))) { @@ -306,7 +264,7 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( D3D12_RESOURCE_DESC upload_buffer_desc; util::FillBufferResourceDesc(upload_buffer_desc, upload_size, D3D12_RESOURCE_FLAG_NONE); - ID3D12Resource* upload_buffer; + Microsoft::WRL::ComPtr upload_buffer; if (SUCCEEDED(device->CreateCommittedResource( &util::kHeapPropertiesUpload, heap_flag_create_not_zeroed, &upload_buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, @@ -333,35 +291,30 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( } upload_buffer->Unmap(0, nullptr); // Defer uploading and transition to the next draw. - PendingTextureUpload& pending_upload = - texture_uploads_pending_.emplace_back(); // While the upload has not been yet completed, keep a reference to the // resource because its lifetime is not tied to that of the // ImmediateTexture (and thus to context's submissions) now. - resource->AddRef(); - pending_upload.texture = resource; - pending_upload.buffer = upload_buffer; + PendingTextureUpload& pending_upload = + texture_uploads_pending_.emplace_back(resource.Get(), + upload_buffer.Get()); } else { XELOGE( - "Failed to map a Direct3D 12 upload buffer for a {}x{} texture for " - "immediate drawing", + "D3D12ImmediateDrawer: Failed to map an upload buffer for a {}x{} " + "texture", width, height); - upload_buffer->Release(); - resource->Release(); - resource = nullptr; + upload_buffer.Reset(); + resource.Reset(); } } else { XELOGE( - "Failed to create a Direct3D 12 upload buffer for a {}x{} texture " - "for immediate drawing", + "D3D12ImmediateDrawer: Failed to create an upload buffer for a {}x{} " + "texture", width, height); - resource->Release(); - resource = nullptr; + resource.Reset(); } } else { - XELOGE("Failed to create a {}x{} Direct3D 12 texture for immediate drawing", - width, height); - resource = nullptr; + XELOGE("D3D12ImmediateDrawer: Failed to create a {}x{} texture", width, + height); } SamplerIndex sampler_index; @@ -376,35 +329,38 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( // Manage by this immediate drawer if successfully created a resource. std::unique_ptr texture = std::make_unique( - width, height, resource, sampler_index, resource ? this : nullptr, - textures_.size()); + width, height, resource.Get(), sampler_index, + resource ? this : nullptr, textures_.size()); if (resource) { textures_.push_back(texture.get()); - // D3D12ImmediateTexture now holds a reference. - resource->Release(); } return std::move(texture); } -void D3D12ImmediateDrawer::Begin(int render_target_width, - int render_target_height) { - assert_null(current_command_list_); +void D3D12ImmediateDrawer::Begin(UIDrawContext& ui_draw_context, + float coordinate_space_width, + float coordinate_space_height) { + ImmediateDrawer::Begin(ui_draw_context, coordinate_space_width, + coordinate_space_height); + assert_false(batch_open_); - ID3D12Device* device = context_.GetD3D12Provider().GetDevice(); + const D3D12UIDrawContext& d3d12_ui_draw_context = + static_cast(ui_draw_context); - // Use the compositing command list. - current_command_list_ = context_.GetSwapCommandList(); - - uint64_t completed_fence_value = context_.GetSwapCompletedFenceValue(); + // Update the submission index to be used throughout the current immediate + // drawer paint. + last_paint_submission_index_ = + d3d12_ui_draw_context.submission_index_current(); + last_completed_submission_index_ = + d3d12_ui_draw_context.submission_index_completed(); // Release deleted textures. for (auto it = textures_deleted_.begin(); it != textures_deleted_.end();) { - if (it->second > completed_fence_value) { + if (it->second > last_completed_submission_index_) { ++it; continue; } - it->first->Release(); if (std::next(it) != textures_deleted_.end()) { *it = textures_deleted_.back(); } @@ -414,37 +370,45 @@ void D3D12ImmediateDrawer::Begin(int render_target_width, // Release upload buffers for completed texture uploads. auto erase_uploads_end = texture_uploads_submitted_.begin(); while (erase_uploads_end != texture_uploads_submitted_.end()) { - if (erase_uploads_end->fence_value > completed_fence_value) { + if (erase_uploads_end->submission_index > + last_completed_submission_index_) { break; } - erase_uploads_end->buffer->Release(); - // Release the texture reference held for uploading. - erase_uploads_end->texture->Release(); ++erase_uploads_end; } texture_uploads_submitted_.erase(texture_uploads_submitted_.begin(), erase_uploads_end); - vertex_buffer_pool_->Reclaim(completed_fence_value); - texture_descriptor_pool_->Reclaim(completed_fence_value); + // Make sure textures created before the current frame are uploaded, even if + // nothing was drawn in the previous frames or nothing will be drawn in the + // current or subsequent ones, as that would result in upload buffers kept + // forever. + UploadTextures(); + + texture_descriptor_pool_->Reclaim(last_completed_submission_index_); + vertex_buffer_pool_->Reclaim(last_completed_submission_index_); + + // Begin drawing. + + ID3D12GraphicsCommandList* command_list = + d3d12_ui_draw_context.command_list(); - current_render_target_width_ = render_target_width; - current_render_target_height_ = render_target_height; D3D12_VIEWPORT viewport; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; - viewport.Width = float(render_target_width); - viewport.Height = float(render_target_height); + viewport.Width = float(d3d12_ui_draw_context.render_target_width()); + viewport.Height = float(d3d12_ui_draw_context.render_target_height()); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; - current_command_list_->RSSetViewports(1, &viewport); + command_list->RSSetViewports(1, &viewport); - current_command_list_->SetGraphicsRootSignature(root_signature_); - float viewport_inv_size[2]; - viewport_inv_size[0] = 1.0f / viewport.Width; - viewport_inv_size[1] = 1.0f / viewport.Height; - current_command_list_->SetGraphicsRoot32BitConstants( - UINT(RootParameter::kViewportSizeInv), 2, viewport_inv_size, 0); + command_list->SetGraphicsRootSignature(root_signature_.Get()); + float coordinate_space_size_inv[2]; + coordinate_space_size_inv[0] = 1.0f / coordinate_space_width; + coordinate_space_size_inv[1] = 1.0f / coordinate_space_height; + command_list->SetGraphicsRoot32BitConstants( + UINT(RootParameter::kCoordinateSpaceSizeInv), 2, + coordinate_space_size_inv, 0); current_scissor_.left = 0; current_scissor_.top = 0; @@ -460,9 +424,12 @@ void D3D12ImmediateDrawer::Begin(int render_target_width, void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { assert_false(batch_open_); - assert_not_null(current_command_list_); - uint64_t current_fence_value = context_.GetSwapCurrentFenceValue(); + const D3D12UIDrawContext& d3d12_ui_draw_context = + *static_cast(ui_draw_context()); + + ID3D12GraphicsCommandList* command_list = + d3d12_ui_draw_context.command_list(); // Bind the vertices. D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view; @@ -470,16 +437,16 @@ void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { vertex_buffer_view.SizeInBytes = UINT(sizeof(ImmediateVertex)) * batch.vertex_count; void* vertex_buffer_mapping = vertex_buffer_pool_->Request( - current_fence_value, vertex_buffer_view.SizeInBytes, sizeof(float), - nullptr, nullptr, &vertex_buffer_view.BufferLocation); + last_paint_submission_index_, vertex_buffer_view.SizeInBytes, + sizeof(float), nullptr, nullptr, &vertex_buffer_view.BufferLocation); if (vertex_buffer_mapping == nullptr) { - XELOGE("Failed to get a buffer for {} vertices in the immediate drawer", + XELOGE("D3D12ImmediateDrawer: Failed to get a buffer for {} vertices", batch.vertex_count); return; } std::memcpy(vertex_buffer_mapping, batch.vertices, vertex_buffer_view.SizeInBytes); - current_command_list_->IASetVertexBuffers(0, 1, &vertex_buffer_view); + command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view); // Bind the indices. batch_has_index_buffer_ = batch.indices != nullptr; @@ -488,16 +455,16 @@ void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { index_buffer_view.SizeInBytes = UINT(sizeof(uint16_t)) * batch.index_count; index_buffer_view.Format = DXGI_FORMAT_R16_UINT; void* index_buffer_mapping = vertex_buffer_pool_->Request( - current_fence_value, index_buffer_view.SizeInBytes, sizeof(uint16_t), - nullptr, nullptr, &index_buffer_view.BufferLocation); + last_paint_submission_index_, index_buffer_view.SizeInBytes, + sizeof(uint16_t), nullptr, nullptr, &index_buffer_view.BufferLocation); if (index_buffer_mapping == nullptr) { - XELOGE("Failed to get a buffer for {} indices in the immediate drawer", + XELOGE("D3D12ImmediateDrawer: Failed to get a buffer for {} indices", batch.index_count); return; } std::memcpy(index_buffer_mapping, batch.indices, index_buffer_view.SizeInBytes); - current_command_list_->IASetIndexBuffer(&index_buffer_view); + command_list->IASetIndexBuffer(&index_buffer_view); } batch_open_ = true; @@ -509,30 +476,30 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { return; } - // Set the scissor rectangle if enabled. - D3D12_RECT scissor; - if (draw.scissor) { - scissor.left = draw.scissor_rect[0]; - scissor.top = current_render_target_height_ - - (draw.scissor_rect[1] + draw.scissor_rect[3]); - scissor.right = scissor.left + draw.scissor_rect[2]; - scissor.bottom = scissor.top + draw.scissor_rect[3]; - } else { - scissor.left = 0; - scissor.top = 0; - scissor.right = current_render_target_width_; - scissor.bottom = current_render_target_height_; - } - if (scissor.right <= scissor.left || scissor.bottom <= scissor.top) { - // Nothing is visible (used as the default current_scissor_ value also). + const D3D12UIDrawContext& d3d12_ui_draw_context = + *static_cast(ui_draw_context()); + ID3D12GraphicsCommandList* command_list = + d3d12_ui_draw_context.command_list(); + + // Set the scissor rectangle. + uint32_t scissor_left, scissor_top, scissor_width, scissor_height; + if (!ScissorToRenderTarget(draw, scissor_left, scissor_top, scissor_width, + scissor_height)) { + // Nothing is visible (zero area is used as the default current_scissor_ + // value also). return; } + D3D12_RECT scissor; + scissor.left = LONG(scissor_left); + scissor.top = LONG(scissor_top); + scissor.right = LONG(scissor_left + scissor_width); + scissor.bottom = LONG(scissor_top + scissor_height); if (current_scissor_.left != scissor.left || current_scissor_.top != scissor.top || current_scissor_.right != scissor.right || current_scissor_.bottom != scissor.bottom) { current_scissor_ = scissor; - current_command_list_->RSSetScissorRects(1, &scissor); + command_list->RSSetScissorRects(1, &scissor); } // Ensure texture data is available if any texture is loaded, upload all in a @@ -542,30 +509,27 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { // Bind the texture. If this is the first draw in a frame, the descriptor heap // index will be invalid initially, and the texture will be bound regardless // of what's in current_texture_. - uint64_t current_fence_value = context_.GetSwapCurrentFenceValue(); auto texture = static_cast(draw.texture); ID3D12Resource* texture_resource = texture ? texture->resource() : nullptr; bool bind_texture = current_texture_ != texture_resource; uint32_t texture_descriptor_index; uint64_t texture_heap_index = texture_descriptor_pool_->Request( - current_fence_value, current_texture_descriptor_heap_index_, + last_paint_submission_index_, current_texture_descriptor_heap_index_, bind_texture ? 1 : 0, 1, texture_descriptor_index); if (texture_heap_index == D3D12DescriptorHeapPool::kHeapIndexInvalid) { return; } if (texture_resource) { - texture->SetLastUsageFenceValue(current_fence_value); + texture->SetLastUsageSubmissionIndex(last_paint_submission_index_); } if (current_texture_descriptor_heap_index_ != texture_heap_index) { current_texture_descriptor_heap_index_ = texture_heap_index; bind_texture = true; ID3D12DescriptorHeap* descriptor_heaps[] = { - texture_descriptor_pool_->GetLastRequestHeap(), sampler_heap_}; - current_command_list_->SetDescriptorHeaps(2, descriptor_heaps); + texture_descriptor_pool_->GetLastRequestHeap(), sampler_heap_.Get()}; + command_list->SetDescriptorHeaps(2, descriptor_heaps); } - const D3D12Provider& provider = context_.GetD3D12Provider(); - if (bind_texture) { current_texture_ = texture_resource; D3D12_SHADER_RESOURCE_VIEW_DESC texture_view_desc; @@ -587,14 +551,14 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { texture_view_desc.Texture2D.MipLevels = 1; texture_view_desc.Texture2D.PlaneSlice = 0; texture_view_desc.Texture2D.ResourceMinLODClamp = 0.0f; - provider.GetDevice()->CreateShaderResourceView( + provider_.GetDevice()->CreateShaderResourceView( texture_resource, &texture_view_desc, - provider.OffsetViewDescriptor( + provider_.OffsetViewDescriptor( texture_descriptor_pool_->GetLastRequestHeapCPUStart(), texture_descriptor_index)); - current_command_list_->SetGraphicsRootDescriptorTable( + command_list->SetGraphicsRootDescriptorTable( UINT(RootParameter::kTexture), - provider.OffsetViewDescriptor( + provider_.OffsetViewDescriptor( texture_descriptor_pool_->GetLastRequestHeapGPUStart(), texture_descriptor_index)); } @@ -605,10 +569,10 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { texture_resource ? texture->sampler_index() : SamplerIndex::kNearestClamp; if (current_sampler_index_ != sampler_index) { current_sampler_index_ = sampler_index; - current_command_list_->SetGraphicsRootDescriptorTable( + command_list->SetGraphicsRootDescriptorTable( UINT(RootParameter::kSampler), - provider.OffsetSamplerDescriptor(sampler_heap_gpu_start_, - uint32_t(sampler_index))); + provider_.OffsetSamplerDescriptor(sampler_heap_gpu_start_, + uint32_t(sampler_index))); } // Set the primitive type and the pipeline for it. @@ -617,11 +581,11 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { switch (draw.primitive_type) { case ImmediatePrimitiveType::kLines: primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; - pipeline = pipeline_line_; + pipeline = pipeline_line_.Get(); break; case ImmediatePrimitiveType::kTriangles: primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - pipeline = pipeline_triangle_; + pipeline = pipeline_triangle_.Get(); break; default: assert_unhandled_case(draw.primitive_type); @@ -629,16 +593,16 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { } if (current_primitive_topology_ != primitive_topology) { current_primitive_topology_ = primitive_topology; - current_command_list_->IASetPrimitiveTopology(primitive_topology); - current_command_list_->SetPipelineState(pipeline); + command_list->IASetPrimitiveTopology(primitive_topology); + command_list->SetPipelineState(pipeline); } // Draw. if (batch_has_index_buffer_) { - current_command_list_->DrawIndexedInstanced( - draw.count, 1, draw.index_offset, draw.base_vertex, 0); + command_list->DrawIndexedInstanced(draw.count, 1, draw.index_offset, + draw.base_vertex, 0); } else { - current_command_list_->DrawInstanced(draw.count, 1, draw.base_vertex, 0); + command_list->DrawInstanced(draw.count, 1, draw.base_vertex, 0); } } @@ -646,11 +610,29 @@ void D3D12ImmediateDrawer::EndDrawBatch() { batch_open_ = false; } void D3D12ImmediateDrawer::End() { assert_false(batch_open_); - if (current_command_list_) { - // Don't keep upload buffers forever if nothing was drawn in this frame. - UploadTextures(); - current_command_list_ = nullptr; + + ImmediateDrawer::End(); +} + +void D3D12ImmediateDrawer::OnLeavePresenter() { + // Leaving the presenter's submission timeline - await GPU usage completion of + // all draws and texture uploads (which happen before draws) and reset + // submission indices. + D3D12Presenter& d3d12_presenter = *static_cast(presenter()); + d3d12_presenter.AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + + for (D3D12ImmediateTexture* texture : textures_) { + texture->SetLastUsageSubmissionIndex(0); } + + texture_uploads_submitted_.clear(); + + vertex_buffer_pool_->ChangeSubmissionTimeline(); + texture_descriptor_pool_->ChangeSubmissionTimeline(); + + last_paint_submission_index_ = 0; + last_completed_submission_index_ = 0; } void D3D12ImmediateDrawer::OnImmediateTextureDestroyed( @@ -665,35 +647,35 @@ void D3D12ImmediateDrawer::OnImmediateTextureDestroyed( // Queue for delayed release. ID3D12Resource* resource = texture.resource(); - uint64_t last_usage_fence_value = texture.last_usage_fence_value(); + UINT64 last_usage_submission_index = texture.last_usage_submission_index(); if (resource && - last_usage_fence_value > context_.GetSwapCompletedFenceValue()) { - resource->AddRef(); - textures_deleted_.push_back( - std::make_pair(resource, last_usage_fence_value)); + last_usage_submission_index > last_completed_submission_index_) { + textures_deleted_.emplace_back(resource, last_usage_submission_index); } } void D3D12ImmediateDrawer::UploadTextures() { - assert_not_null(current_command_list_); if (texture_uploads_pending_.empty()) { // Called often - don't initialize anything. return; } - ID3D12Device* device = context_.GetD3D12Provider().GetDevice(); - uint64_t current_fence_value = context_.GetSwapCurrentFenceValue(); + ID3D12Device* device = provider_.GetDevice(); + const D3D12UIDrawContext& d3d12_ui_draw_context = + *static_cast(ui_draw_context()); + ID3D12GraphicsCommandList* command_list = + d3d12_ui_draw_context.command_list(); // Copy all at once, then transition all at once (not interleaving copying and // pipeline barriers). std::vector barriers; barriers.reserve(texture_uploads_pending_.size()); for (const PendingTextureUpload& pending_upload : texture_uploads_pending_) { - ID3D12Resource* texture = pending_upload.texture; + ID3D12Resource* texture = pending_upload.texture.Get(); D3D12_RESOURCE_DESC texture_desc = texture->GetDesc(); D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; - location_source.pResource = pending_upload.buffer; + location_source.pResource = pending_upload.buffer.Get(); location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; device->GetCopyableFootprints(&texture_desc, 0, 1, 0, &location_source.PlacedFootprint, nullptr, @@ -701,8 +683,8 @@ void D3D12ImmediateDrawer::UploadTextures() { location_dest.pResource = texture; location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; location_dest.SubresourceIndex = 0; - current_command_list_->CopyTextureRegion(&location_dest, 0, 0, 0, - &location_source, nullptr); + command_list->CopyTextureRegion(&location_dest, 0, 0, 0, &location_source, + nullptr); D3D12_RESOURCE_BARRIER& barrier = barriers.emplace_back(); barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; @@ -712,18 +694,12 @@ void D3D12ImmediateDrawer::UploadTextures() { barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - SubmittedTextureUpload& submitted_upload = - texture_uploads_submitted_.emplace_back(); - // Transfer the reference to the texture - need to keep it until the upload - // is completed. - submitted_upload.texture = texture; - submitted_upload.buffer = pending_upload.buffer; - submitted_upload.fence_value = current_fence_value; + texture_uploads_submitted_.emplace_back( + texture, pending_upload.buffer.Get(), last_paint_submission_index_); } texture_uploads_pending_.clear(); assert_false(barriers.empty()); - current_command_list_->ResourceBarrier(UINT(barriers.size()), - barriers.data()); + command_list->ResourceBarrier(UINT(barriers.size()), barriers.data()); } } // namespace d3d12 diff --git a/src/xenia/ui/d3d12/d3d12_immediate_drawer.h b/src/xenia/ui/d3d12/d3d12_immediate_drawer.h index fbc362f59..2c3691e1f 100644 --- a/src/xenia/ui/d3d12/d3d12_immediate_drawer.h +++ b/src/xenia/ui/d3d12/d3d12_immediate_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,6 +17,7 @@ #include "xenia/ui/d3d12/d3d12_api.h" #include "xenia/ui/d3d12/d3d12_descriptor_heap_pool.h" +#include "xenia/ui/d3d12/d3d12_provider.h" #include "xenia/ui/d3d12/d3d12_upload_buffer_pool.h" #include "xenia/ui/immediate_drawer.h" @@ -24,15 +25,19 @@ namespace xe { namespace ui { namespace d3d12 { -class D3D12Context; - -class D3D12ImmediateDrawer : public ImmediateDrawer { +class D3D12ImmediateDrawer final : public ImmediateDrawer { public: - D3D12ImmediateDrawer(D3D12Context& graphics_context); - ~D3D12ImmediateDrawer() override; + static std::unique_ptr Create( + const D3D12Provider& provider) { + auto immediate_drawer = std::unique_ptr( + new D3D12ImmediateDrawer(provider)); + if (!immediate_drawer->Initialize()) { + return nullptr; + } + return std::move(immediate_drawer); + } - bool Initialize(); - void Shutdown(); + ~D3D12ImmediateDrawer(); std::unique_ptr CreateTexture(uint32_t width, uint32_t height, @@ -40,12 +45,16 @@ class D3D12ImmediateDrawer : public ImmediateDrawer { bool is_repeated, const uint8_t* data) override; - void Begin(int render_target_width, int render_target_height) override; + void Begin(UIDrawContext& ui_draw_context, float coordinate_space_width, + float coordinate_space_height) override; void BeginDrawBatch(const ImmediateDrawBatch& batch) override; void Draw(const ImmediateDraw& draw) override; void EndDrawBatch() override; void End() override; + protected: + void OnLeavePresenter() override; + private: enum class SamplerIndex { kNearestClamp, @@ -57,7 +66,7 @@ class D3D12ImmediateDrawer : public ImmediateDrawer { kInvalid = kCount }; - class D3D12ImmediateTexture : public ImmediateTexture { + class D3D12ImmediateTexture final : public ImmediateTexture { public: static constexpr DXGI_FORMAT kFormat = DXGI_FORMAT_R8G8B8A8_UNORM; D3D12ImmediateTexture(uint32_t width, uint32_t height, @@ -66,75 +75,93 @@ class D3D12ImmediateDrawer : public ImmediateDrawer { size_t immediate_drawer_index); ~D3D12ImmediateTexture() override; - ID3D12Resource* resource() const { return resource_; } + ID3D12Resource* resource() const { return resource_.Get(); } SamplerIndex sampler_index() const { return sampler_index_; } size_t immediate_drawer_index() const { return immediate_drawer_index_; } void SetImmediateDrawerIndex(size_t index) { immediate_drawer_index_ = index; } - void OnImmediateDrawerShutdown(); + void OnImmediateDrawerDestroyed(); - uint64_t last_usage_fence_value() const { return last_usage_fence_value_; } - void SetLastUsageFenceValue(uint64_t fence_value) { - last_usage_fence_value_ = fence_value; + UINT64 last_usage_submission_index() const { + return last_usage_submission_index_; + } + void SetLastUsageSubmissionIndex(UINT64 submission_index) { + last_usage_submission_index_ = submission_index; } private: - ID3D12Resource* resource_; + Microsoft::WRL::ComPtr resource_; SamplerIndex sampler_index_; D3D12ImmediateDrawer* immediate_drawer_; size_t immediate_drawer_index_; - uint64_t last_usage_fence_value_ = 0; + UINT64 last_usage_submission_index_ = 0; }; + D3D12ImmediateDrawer(const D3D12Provider& provider) : provider_(provider) {} + bool Initialize(); + void OnImmediateTextureDestroyed(D3D12ImmediateTexture& texture); void UploadTextures(); - D3D12Context& context_; + const D3D12Provider& provider_; - ID3D12RootSignature* root_signature_ = nullptr; + Microsoft::WRL::ComPtr root_signature_; enum class RootParameter { kTexture, kSampler, - kViewportSizeInv, + kCoordinateSpaceSizeInv, kCount }; - ID3D12PipelineState* pipeline_triangle_ = nullptr; - ID3D12PipelineState* pipeline_line_ = nullptr; + Microsoft::WRL::ComPtr pipeline_triangle_; + Microsoft::WRL::ComPtr pipeline_line_; - ID3D12DescriptorHeap* sampler_heap_ = nullptr; + Microsoft::WRL::ComPtr sampler_heap_; D3D12_CPU_DESCRIPTOR_HANDLE sampler_heap_cpu_start_; D3D12_GPU_DESCRIPTOR_HANDLE sampler_heap_gpu_start_; - std::unique_ptr vertex_buffer_pool_; - std::unique_ptr texture_descriptor_pool_; - // Only with non-null resources. std::vector textures_; struct PendingTextureUpload { - ID3D12Resource* texture; - ID3D12Resource* buffer; + PendingTextureUpload(ID3D12Resource* texture, ID3D12Resource* buffer) + : texture(texture), buffer(buffer) {} + Microsoft::WRL::ComPtr texture; + Microsoft::WRL::ComPtr buffer; }; std::vector texture_uploads_pending_; struct SubmittedTextureUpload { - ID3D12Resource* texture; - ID3D12Resource* buffer; - uint64_t fence_value; + SubmittedTextureUpload(ID3D12Resource* texture, ID3D12Resource* buffer, + UINT64 submission_index) + : texture(texture), + buffer(buffer), + submission_index(submission_index) {} + Microsoft::WRL::ComPtr texture; + Microsoft::WRL::ComPtr buffer; + UINT64 submission_index; }; std::deque texture_uploads_submitted_; - std::vector> textures_deleted_; + std::deque, UINT64>> + textures_deleted_; + + std::unique_ptr vertex_buffer_pool_; + std::unique_ptr texture_descriptor_pool_; + + // The submission index within the current Begin (or the last, if outside + // one). + UINT64 last_paint_submission_index_ = 0; + // Completed submission index as of the latest Begin, to coarsely skip delayed + // texture deletion. + UINT64 last_completed_submission_index_ = 0; - ID3D12GraphicsCommandList* current_command_list_ = nullptr; - int current_render_target_width_, current_render_target_height_; bool batch_open_ = false; bool batch_has_index_buffer_; D3D12_RECT current_scissor_; diff --git a/src/xenia/ui/d3d12/d3d12_presenter.cc b/src/xenia/ui/d3d12/d3d12_presenter.cc new file mode 100644 index 000000000..574b66d0d --- /dev/null +++ b/src/xenia/ui/d3d12/d3d12_presenter.cc @@ -0,0 +1,1466 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/d3d12/d3d12_presenter.h" + +#include +#include +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/cvar.h" +#include "xenia/base/logging.h" +#include "xenia/base/math.h" +#include "xenia/ui/d3d12/d3d12_provider.h" +#include "xenia/ui/d3d12/d3d12_util.h" +#include "xenia/ui/surface_win.h" + +DEFINE_bool( + d3d12_allow_variable_refresh_rate_and_tearing, true, + "In fullscreen, allow using variable refresh rate on displays supporting " + "it. On displays not supporting VRR, screen tearing may occur in certain " + "cases.", + "D3D12"); + +namespace xe { +namespace ui { +namespace d3d12 { + +// Generated with `xb buildshaders`. +namespace shaders { +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h" +} // namespace shaders + +D3D12Presenter::~D3D12Presenter() { + // Await completion of the usage of everything before destroying anything. + // From most likely the latest to most likely the earliest to be signaled, so + // just one sleep will likely be needed. + paint_context_.AwaitSwapChainUsageCompletion(); + guest_output_resource_refresher_submission_tracker_.Shutdown(); + ui_submission_tracker_.Shutdown(); +} + +Surface::TypeFlags D3D12Presenter::GetSupportedSurfaceTypes() const { + Surface::TypeFlags types = 0; +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) + types |= Surface::kTypeFlag_Win32Hwnd; +#endif + return types; +} + +bool D3D12Presenter::CaptureGuestOutput(RawImage& image_out) { + Microsoft::WRL::ComPtr guest_output_resource; + { + uint32_t guest_output_mailbox_index; + std::unique_lock guest_output_consumer_lock( + ConsumeGuestOutput(guest_output_mailbox_index, nullptr, nullptr)); + if (guest_output_mailbox_index != UINT32_MAX) { + guest_output_resource = + guest_output_resources_[guest_output_mailbox_index].second; + } + // Incremented the reference count of the guest output resource - safe to + // leave the consumer critical section now. + } + if (!guest_output_resource) { + return false; + } + + ID3D12Device* device = provider_.GetDevice(); + + D3D12_RESOURCE_DESC texture_desc = guest_output_resource->GetDesc(); + D3D12_TEXTURE_COPY_LOCATION copy_dest; + UINT64 copy_dest_size; + device->GetCopyableFootprints(&texture_desc, 0, 1, 0, + ©_dest.PlacedFootprint, nullptr, nullptr, + ©_dest_size); + + D3D12_RESOURCE_DESC buffer_desc; + util::FillBufferResourceDesc(buffer_desc, copy_dest_size, + D3D12_RESOURCE_FLAG_NONE); + Microsoft::WRL::ComPtr buffer; + // Create zeroed not to leak data in the row padding. + if (FAILED(device->CreateCommittedResource( + &util::kHeapPropertiesReadback, D3D12_HEAP_FLAG_NONE, &buffer_desc, + D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&buffer)))) { + XELOGE("D3D12Presenter: Failed to create the guest output capture buffer"); + return false; + } + + { + Microsoft::WRL::ComPtr command_allocator; + if (FAILED( + device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&command_allocator)))) { + XELOGE( + "D3D12Presenter: Failed to create the guest output capturing command " + "allocator"); + return false; + } + Microsoft::WRL::ComPtr command_list; + if (FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, + command_allocator.Get(), nullptr, + IID_PPV_ARGS(&command_list)))) { + XELOGE( + "D3D12Presenter: Failed to create the guest output capturing command " + "list"); + return false; + } + + D3D12_RESOURCE_BARRIER barrier; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = guest_output_resource.Get(); + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = kGuestOutputInternalState; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; + if constexpr (kGuestOutputInternalState != + D3D12_RESOURCE_STATE_COPY_SOURCE) { + command_list->ResourceBarrier(1, &barrier); + } + copy_dest.pResource = buffer.Get(); + copy_dest.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + D3D12_TEXTURE_COPY_LOCATION copy_source; + copy_source.pResource = guest_output_resource.Get(); + copy_source.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + copy_source.SubresourceIndex = 0; + command_list->CopyTextureRegion(©_dest, 0, 0, 0, ©_source, nullptr); + if constexpr (kGuestOutputInternalState != + D3D12_RESOURCE_STATE_COPY_SOURCE) { + std::swap(barrier.Transition.StateBefore, barrier.Transition.StateAfter); + command_list->ResourceBarrier(1, &barrier); + } + if (FAILED(command_list->Close())) { + XELOGE( + "D3D12Presenter: Failed to close the guest output capturing command " + "list"); + return false; + } + + ID3D12CommandQueue* direct_queue = provider_.GetDirectQueue(); + + // Make sure that if any work is submitted, any `return` will cause an await + // before releasing the command allocator / list and the resource the RAII + // way in the destruction of the submission tracker - so create after the + // objects referenced in the submission - but don't submit anything if + // failed to initialize the fence. + D3D12SubmissionTracker submission_tracker; + if (!submission_tracker.Initialize(device, direct_queue)) { + return false; + } + ID3D12CommandList* execute_command_list = command_list.Get(); + direct_queue->ExecuteCommandLists(1, &execute_command_list); + if (!submission_tracker.NextSubmission()) { + XELOGE( + "D3D12Presenter: Failed to signal the guest output capturing fence"); + return false; + } + if (!submission_tracker.AwaitAllSubmissionsCompletion()) { + XELOGE( + "D3D12Presenter: Failed to await the guest output capturing fence"); + return false; + } + } + + D3D12_RANGE read_range; + read_range.Begin = copy_dest.PlacedFootprint.Offset; + read_range.End = copy_dest_size; + void* mapping; + if (FAILED(buffer->Map(0, &read_range, &mapping))) { + XELOGE("D3D12Presenter: Failed to map the guest output capture buffer"); + return false; + } + image_out.width = uint32_t(texture_desc.Width); + image_out.height = uint32_t(texture_desc.Height); + image_out.stride = sizeof(uint32_t) * image_out.width; + image_out.data.resize(image_out.stride * image_out.height); + uint32_t* image_out_pixels = + reinterpret_cast(image_out.data.data()); + for (uint32_t y = 0; y < image_out.height; ++y) { + uint32_t* dest_row = &image_out_pixels[size_t(image_out.width) * y]; + const uint32_t* source_row = reinterpret_cast( + reinterpret_cast(mapping) + + copy_dest.PlacedFootprint.Offset + + size_t(copy_dest.PlacedFootprint.Footprint.RowPitch) * y); + for (uint32_t x = 0; x < image_out.width; ++x) { + dest_row[x] = Packed10bpcRGBTo8bpcBytes(source_row[x]); + } + } + // Unmapping will be done implicitly when the resource goes out of scope and + // gets destroyed. + return true; +} + +Presenter::SurfacePaintConnectResult +D3D12Presenter::ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) { + uint32_t new_swap_chain_width = std::min( + new_surface_width, uint32_t(D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION)); + uint32_t new_swap_chain_height = std::min( + new_surface_height, uint32_t(D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION)); + + // ConnectOrReconnectPaintingToSurfaceFromUIThread may be called only for the + // surface of the current swap chain or when the old swap chain has already + // been destroyed, if the surface is the same, try resizing. + if (paint_context_.swap_chain) { + if (was_paintable && + paint_context_.swap_chain_width == new_swap_chain_width && + paint_context_.swap_chain_height == new_swap_chain_height) { + is_vsync_implicit_out = false; + return SurfacePaintConnectResult::kSuccessUnchanged; + } + paint_context_.AwaitSwapChainUsageCompletion(); + // Using the current swap_chain_allows_tearing_ value that's consistent with + // the creation of the swap chain because ResizeBuffers can't toggle the + // tearing flag. + for (Microsoft::WRL::ComPtr& swap_chain_buffer_ref : + paint_context_.swap_chain_buffers) { + swap_chain_buffer_ref.Reset(); + } + bool swap_chain_resized = + SUCCEEDED(paint_context_.swap_chain->ResizeBuffers( + 0, UINT(new_swap_chain_width), UINT(new_swap_chain_height), + DXGI_FORMAT_UNKNOWN, + paint_context_.swap_chain_allows_tearing + ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING + : 0)); + if (swap_chain_resized) { + for (uint32_t i = 0; i < PaintContext::kSwapChainBufferCount; ++i) { + if (FAILED(paint_context_.swap_chain->GetBuffer( + i, IID_PPV_ARGS(&paint_context_.swap_chain_buffers[i])))) { + swap_chain_resized = false; + break; + } + } + if (swap_chain_resized) { + paint_context_.swap_chain_width = new_swap_chain_width; + paint_context_.swap_chain_height = new_swap_chain_height; + } + } + if (!swap_chain_resized) { + XELOGE("D3D12Presenter: Failed to resize a swap chain"); + // Failed to resize, retry creating from scratch. + paint_context_.DestroySwapChain(); + } + } + + if (!paint_context_.swap_chain) { + // Create a new swap chain. + Surface::TypeIndex surface_type = new_surface.GetType(); + DXGI_SWAP_CHAIN_DESC1 swap_chain_desc; + swap_chain_desc.Width = UINT(new_swap_chain_width); + swap_chain_desc.Height = UINT(new_swap_chain_height); + swap_chain_desc.Format = kSwapChainFormat; + swap_chain_desc.Stereo = FALSE; + swap_chain_desc.SampleDesc.Count = 1; + swap_chain_desc.SampleDesc.Quality = 0; + swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swap_chain_desc.BufferCount = UINT(PaintContext::kSwapChainBufferCount); + // DXGI_SCALING_STRETCH may cause the content to "shake" while resizing, + // with relayout done for the guest output twice visually rather than once, + // and the UI becoming stretched and then jumping to normal. If it's + // possible to cover the entire surface without stretching, don't stretch. + // After resizing, the presenter repaints as soon as possible anyway, so + swap_chain_desc.Scaling = (new_swap_chain_width == new_surface_width && + new_swap_chain_height == new_surface_height) + ? DXGI_SCALING_NONE + : DXGI_SCALING_STRETCH; + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swap_chain_desc.Flags = 0; + if (cvars::d3d12_allow_variable_refresh_rate_and_tearing && + dxgi_supports_tearing_) { + // Allow tearing in borderless fullscreen to support variable refresh + // rate. + swap_chain_desc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + } + IDXGIFactory2* dxgi_factory = provider_.GetDXGIFactory(); + ID3D12CommandQueue* direct_queue = provider_.GetDirectQueue(); + Microsoft::WRL::ComPtr swap_chain_1; + switch (surface_type) { +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) + case Surface::kTypeIndex_Win32Hwnd: { + HWND surface_hwnd = + static_cast(new_surface).hwnd(); + if (FAILED(dxgi_factory->CreateSwapChainForHwnd( + direct_queue, surface_hwnd, &swap_chain_desc, nullptr, nullptr, + &swap_chain_1))) { + XELOGE("D3D12Presenter: Failed to create a swap chain for the HWND"); + return SurfacePaintConnectResult::kFailure; + } + // Disable automatic Alt+Enter handling - DXGI fullscreen doesn't + // support ALLOW_TEARING, and using custom fullscreen in ui::Win32Window + // anyway as with Alt+Enter the menu is kept, state changes are tracked + // better, and nothing is presented for some reason. + dxgi_factory->MakeWindowAssociation(surface_hwnd, + DXGI_MWA_NO_ALT_ENTER); + } break; +#endif + default: + assert_unhandled_case(surface_type); + XELOGE( + "D3D12Presenter: Tried to create a swap chain for an unsupported " + "Xenia surface type"); + return SurfacePaintConnectResult::kFailureSurfaceUnusable; + } + if (FAILED(swap_chain_1->QueryInterface( + IID_PPV_ARGS(&paint_context_.swap_chain)))) { + XELOGE( + "D3D12Presenter: Failed to get version 3 of the swap chain " + "interface"); + return SurfacePaintConnectResult::kFailure; + } + // From now on, in case of any failure, DestroySwapChain must be called + // before returning. + paint_context_.swap_chain_width = new_swap_chain_width; + paint_context_.swap_chain_height = new_swap_chain_height; + paint_context_.swap_chain_allows_tearing = + (swap_chain_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) != 0; + for (uint32_t i = 0; i < PaintContext::kSwapChainBufferCount; ++i) { + if (FAILED(paint_context_.swap_chain->GetBuffer( + i, IID_PPV_ARGS(&paint_context_.swap_chain_buffers[i])))) { + XELOGE( + "D3D12Presenter: Failed to get buffer {} of a {}-buffer swap chain", + i, PaintContext::kSwapChainBufferCount); + paint_context_.DestroySwapChain(); + return SurfacePaintConnectResult::kFailure; + } + } + } + + ID3D12Device* device = provider_.GetDevice(); + + // Create the RTV descriptors. + D3D12_CPU_DESCRIPTOR_HANDLE rtv_heap_start = + paint_context_.rtv_heap->GetCPUDescriptorHandleForHeapStart(); + D3D12_RENDER_TARGET_VIEW_DESC rtv_desc; + rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + rtv_desc.Texture2D.MipSlice = 0; + rtv_desc.Texture2D.PlaneSlice = 0; + for (uint32_t i = 0; i < PaintContext::kSwapChainBufferCount; ++i) { + ID3D12Resource* swap_chain_buffer = + paint_context_.swap_chain_buffers[i].Get(); + rtv_desc.Format = kSwapChainFormat; + device->CreateRenderTargetView( + swap_chain_buffer, &rtv_desc, + provider_.OffsetRTVDescriptor( + rtv_heap_start, PaintContext::kRTVIndexSwapChainBuffer0 + i)); + } + + is_vsync_implicit_out = false; + return SurfacePaintConnectResult::kSuccess; +} + +void D3D12Presenter::DisconnectPaintingFromSurfaceFromUIThreadImpl() { + paint_context_.DestroySwapChain(); +} + +bool D3D12Presenter::RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out_ref) { + assert_not_zero(frontbuffer_width); + assert_not_zero(frontbuffer_height); + std::pair>& + guest_output_resource_ref = guest_output_resources_[mailbox_index]; + if (guest_output_resource_ref.second) { + D3D12_RESOURCE_DESC guest_output_resource_current_desc = + guest_output_resource_ref.second->GetDesc(); + if (guest_output_resource_current_desc.Width != frontbuffer_width || + guest_output_resource_current_desc.Height != frontbuffer_height) { + // Main target painting has its own reference to the textures for reading + // in its own submission tracker timeline, safe to release here. + guest_output_resource_refresher_submission_tracker_ + .AwaitSubmissionCompletion(guest_output_resource_ref.first); + guest_output_resource_ref.second.Reset(); + } + } + if (!guest_output_resource_ref.second) { + ID3D12Device* device = provider_.GetDevice(); + D3D12_RESOURCE_DESC guest_output_resource_new_desc; + guest_output_resource_new_desc.Dimension = + D3D12_RESOURCE_DIMENSION_TEXTURE2D; + guest_output_resource_new_desc.Alignment = 0; + guest_output_resource_new_desc.Width = frontbuffer_width; + guest_output_resource_new_desc.Height = frontbuffer_height; + guest_output_resource_new_desc.DepthOrArraySize = 1; + guest_output_resource_new_desc.MipLevels = 1; + guest_output_resource_new_desc.Format = kGuestOutputFormat; + guest_output_resource_new_desc.SampleDesc.Count = 1; + guest_output_resource_new_desc.SampleDesc.Quality = 0; + guest_output_resource_new_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + guest_output_resource_new_desc.Flags = + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + if (FAILED(device->CreateCommittedResource( + &util::kHeapPropertiesDefault, + provider_.GetHeapFlagCreateNotZeroed(), + &guest_output_resource_new_desc, kGuestOutputInternalState, nullptr, + IID_PPV_ARGS(&guest_output_resource_ref.second)))) { + XELOGE("D3D12Presenter: Failed to create the guest output {}x{} texture", + frontbuffer_width, frontbuffer_height); + return false; + } + } + D3D12GuestOutputRefreshContext context( + is_8bpc_out_ref, guest_output_resource_ref.second.Get()); + bool refresher_succeeded = refresher(context); + // Even if the refresher has returned false, it still might have submitted + // some commands referencing the resource. It's better to put an excessive + // signal and wait slightly longer, for nothing important, while shutting down + // than to destroy the resource while it's still in use. + guest_output_resource_ref.first = + guest_output_resource_refresher_submission_tracker_ + .GetCurrentSubmission(); + guest_output_resource_refresher_submission_tracker_.NextSubmission(); + return refresher_succeeded; +} + +void D3D12Presenter::PaintContext::DestroySwapChain() { + if (!swap_chain) { + return; + } + AwaitSwapChainUsageCompletion(); + for (Microsoft::WRL::ComPtr& swap_chain_buffer_ref : + swap_chain_buffers) { + swap_chain_buffer_ref.Reset(); + } + swap_chain.Reset(); + swap_chain_allows_tearing = false; + swap_chain_height = 0; + swap_chain_width = 0; +} + +Presenter::PaintResult D3D12Presenter::PaintAndPresentImpl( + bool execute_ui_drawers) { + // Begin the command list with the command allocator not currently potentially + // used on the GPU. + UINT64 current_paint_submission = + paint_context_.paint_submission_tracker.GetCurrentSubmission(); + UINT64 command_allocator_count = + UINT64(paint_context_.command_allocators.size()); + if (current_paint_submission >= command_allocator_count) { + paint_context_.paint_submission_tracker.AwaitSubmissionCompletion( + current_paint_submission - command_allocator_count); + } + ID3D12CommandAllocator* command_allocator = + paint_context_ + .command_allocators[current_paint_submission % + command_allocator_count] + .Get(); + command_allocator->Reset(); + ID3D12GraphicsCommandList* command_list = paint_context_.command_list.Get(); + command_list->Reset(command_allocator, nullptr); + + ID3D12Device* device = provider_.GetDevice(); + + // Obtain the RTV heap and the back buffer. + D3D12_CPU_DESCRIPTOR_HANDLE rtv_heap_start = + paint_context_.rtv_heap->GetCPUDescriptorHandleForHeapStart(); + UINT back_buffer_index = + paint_context_.swap_chain->GetCurrentBackBufferIndex(); + D3D12_CPU_DESCRIPTOR_HANDLE back_buffer_rtv = provider_.OffsetRTVDescriptor( + rtv_heap_start, + PaintContext::kRTVIndexSwapChainBuffer0 + back_buffer_index); + ID3D12Resource* back_buffer = + paint_context_.swap_chain_buffers[back_buffer_index].Get(); + bool back_buffer_acquired = false; + bool back_buffer_bound = false; + bool back_buffer_clear_needed = true; + const float kBackBufferClearColor[] = {0.0f, 0.0f, 0.0f, 1.0f}; + + // Draw the guest output. + + GuestOutputProperties guest_output_properties; + GuestOutputPaintConfig guest_output_paint_config; + Microsoft::WRL::ComPtr guest_output_resource; + { + uint32_t guest_output_mailbox_index; + std::unique_lock guest_output_consumer_lock( + ConsumeGuestOutput(guest_output_mailbox_index, &guest_output_properties, + &guest_output_paint_config)); + if (guest_output_mailbox_index != UINT32_MAX) { + guest_output_resource = + guest_output_resources_[guest_output_mailbox_index].second; + } + // Incremented the reference count of the guest output resource - safe to + // leave the consumer critical section now as everything here either will be + // using the new reference or is exclusively owned by main target painting + // (and multiple threads can't paint the main target at the same time). + } + + if (guest_output_resource) { + GuestOutputPaintFlow guest_output_flow = GetGuestOutputPaintFlow( + guest_output_properties, paint_context_.swap_chain_width, + paint_context_.swap_chain_height, D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION, + D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION, guest_output_paint_config); + + // Check if all guest output paint effects are supported by the + // implementation. + if (guest_output_flow.effect_count) { + if (!guest_output_paint_final_pipelines_[size_t( + guest_output_flow.effects[guest_output_flow.effect_count - 1])]) { + guest_output_flow.effect_count = 0; + } + for (size_t i = 0; i + 1 < guest_output_flow.effect_count; ++i) { + if (!guest_output_paint_intermediate_pipelines_[size_t( + guest_output_flow.effects[i])]) { + guest_output_flow.effect_count = 0; + break; + } + } + } + + if (guest_output_flow.effect_count) { + ID3D12DescriptorHeap* view_heap = paint_context_.view_heap.Get(); + D3D12_CPU_DESCRIPTOR_HANDLE view_heap_cpu_start = + view_heap->GetCPUDescriptorHandleForHeapStart(); + + // Store the main target reference to the guest output texture so it's not + // destroyed while it's still potentially in use by main target painting + // queued on the GPU. + size_t guest_output_resource_paint_ref_index = SIZE_MAX; + size_t guest_output_resource_paint_ref_new_index = SIZE_MAX; + // Try to find the existing reference to the same texture, or an already + // released (or a taken, but never actually used) slot. + for (size_t i = 0; + i < paint_context_.guest_output_resource_paint_refs.size(); ++i) { + const std::pair>& + guest_output_resource_paint_ref = + paint_context_.guest_output_resource_paint_refs[i]; + if (guest_output_resource_paint_ref.second == guest_output_resource) { + guest_output_resource_paint_ref_index = i; + break; + } + if (guest_output_resource_paint_ref_new_index == SIZE_MAX && + (!guest_output_resource_paint_ref.second || + !guest_output_resource_paint_ref.first)) { + guest_output_resource_paint_ref_new_index = i; + } + } + if (guest_output_resource_paint_ref_index == SIZE_MAX) { + // New texture - store the reference and create the descriptors. + if (guest_output_resource_paint_ref_new_index == SIZE_MAX) { + // Replace the earliest used reference. + guest_output_resource_paint_ref_new_index = 0; + for (size_t i = 1; + i < paint_context_.guest_output_resource_paint_refs.size(); + ++i) { + if (paint_context_.guest_output_resource_paint_refs[i].first < + paint_context_ + .guest_output_resource_paint_refs + [guest_output_resource_paint_ref_new_index] + .first) { + guest_output_resource_paint_ref_new_index = i; + } + } + // Await the completion of the usage of the old guest output + // resource and its SRV descriptors. + paint_context_.paint_submission_tracker.AwaitSubmissionCompletion( + paint_context_ + .guest_output_resource_paint_refs + [guest_output_resource_paint_ref_new_index] + .first); + } + guest_output_resource_paint_ref_index = + guest_output_resource_paint_ref_new_index; + // The actual submission index will be set if the texture is actually + // used, not dropped due to some error. + paint_context_.guest_output_resource_paint_refs + [guest_output_resource_paint_ref_index] = + std::make_pair(UINT64(0), guest_output_resource); + // Create the SRV descriptor of the new texture. + D3D12_SHADER_RESOURCE_VIEW_DESC guest_output_resource_srv_desc; + guest_output_resource_srv_desc.Format = kGuestOutputFormat; + guest_output_resource_srv_desc.ViewDimension = + D3D12_SRV_DIMENSION_TEXTURE2D; + guest_output_resource_srv_desc.Shader4ComponentMapping = + D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + guest_output_resource_srv_desc.Texture2D.MostDetailedMip = 0; + guest_output_resource_srv_desc.Texture2D.MipLevels = 1; + guest_output_resource_srv_desc.Texture2D.PlaneSlice = 0; + guest_output_resource_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; + device->CreateShaderResourceView( + guest_output_resource.Get(), &guest_output_resource_srv_desc, + provider_.OffsetViewDescriptor( + view_heap_cpu_start, + PaintContext::kViewIndexGuestOutput0Srv + + uint32_t(guest_output_resource_paint_ref_index))); + } + + // Make sure intermediate textures of the needed size are available, and + // unneeded intermediate textures are destroyed. + for (size_t i = 0; i < kMaxGuestOutputPaintEffects - 1; ++i) { + std::pair intermediate_needed_size(0, 0); + if (i + 1 < guest_output_flow.effect_count) { + intermediate_needed_size = guest_output_flow.effect_output_sizes[i]; + } + Microsoft::WRL::ComPtr& intermediate_texture_ptr_ref = + paint_context_.guest_output_intermediate_textures[i]; + std::pair intermediate_current_size(0, 0); + if (intermediate_texture_ptr_ref) { + D3D12_RESOURCE_DESC intermediate_current_desc = + intermediate_texture_ptr_ref->GetDesc(); + intermediate_current_size.first = + uint32_t(intermediate_current_desc.Width); + intermediate_current_size.second = intermediate_current_desc.Height; + } + if (intermediate_current_size != intermediate_needed_size) { + if (intermediate_needed_size.first && + intermediate_needed_size.second) { + // Need to replace immediately as a new texture with the requested + // size is needed. + if (intermediate_texture_ptr_ref) { + paint_context_.paint_submission_tracker.AwaitSubmissionCompletion( + paint_context_.guest_output_intermediate_texture_last_usage); + intermediate_texture_ptr_ref.Reset(); + } + // Resource. + D3D12_RESOURCE_DESC intermediate_desc; + intermediate_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + intermediate_desc.Alignment = 0; + intermediate_desc.Width = intermediate_needed_size.first; + intermediate_desc.Height = intermediate_needed_size.second; + intermediate_desc.DepthOrArraySize = 1; + intermediate_desc.MipLevels = 1; + intermediate_desc.Format = kGuestOutputIntermediateFormat; + intermediate_desc.SampleDesc.Count = 1; + intermediate_desc.SampleDesc.Quality = 0; + intermediate_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + intermediate_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + if (FAILED(device->CreateCommittedResource( + &util::kHeapPropertiesDefault, + provider_.GetHeapFlagCreateNotZeroed(), &intermediate_desc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, + IID_PPV_ARGS(&intermediate_texture_ptr_ref)))) { + XELOGE( + "D3D12Presenter: Failed to create a guest output " + "presentation intermediate texture"); + // Don't display the guest output, and don't try to create more + // intermediate textures (only destroy them). + guest_output_flow.effect_count = 0; + continue; + } + ID3D12Resource* intermediate_texture = + intermediate_texture_ptr_ref.Get(); + // SRV. + D3D12_SHADER_RESOURCE_VIEW_DESC intermediate_srv_desc; + intermediate_srv_desc.Format = kGuestOutputIntermediateFormat; + intermediate_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + intermediate_srv_desc.Shader4ComponentMapping = + D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + intermediate_srv_desc.Texture2D.MostDetailedMip = 0; + intermediate_srv_desc.Texture2D.MipLevels = 1; + intermediate_srv_desc.Texture2D.PlaneSlice = 0; + intermediate_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; + device->CreateShaderResourceView( + intermediate_texture, &intermediate_srv_desc, + provider_.OffsetViewDescriptor( + view_heap_cpu_start, + uint32_t( + PaintContext::kViewIndexGuestOutputIntermediate0Srv + + i))); + // RTV. + D3D12_RENDER_TARGET_VIEW_DESC intermediate_rtv_desc; + intermediate_rtv_desc.Format = kGuestOutputIntermediateFormat; + intermediate_rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + intermediate_rtv_desc.Texture2D.MipSlice = 0; + intermediate_rtv_desc.Texture2D.PlaneSlice = 0; + device->CreateRenderTargetView( + intermediate_texture, &intermediate_rtv_desc, + provider_.OffsetRTVDescriptor( + rtv_heap_start, + uint32_t(PaintContext::kRTVIndexGuestOutputIntermediate0 + + i))); + } else { + // Was previously needed, but not anymore - destroy when possible. + if (intermediate_texture_ptr_ref && + paint_context_.paint_submission_tracker + .GetCompletedSubmission() >= + paint_context_ + .guest_output_intermediate_texture_last_usage) { + intermediate_texture_ptr_ref.Reset(); + } + } + } + } + + if (guest_output_flow.effect_count) { + paint_context_ + .guest_output_resource_paint_refs + [guest_output_resource_paint_ref_index] + .first = current_paint_submission; + if (guest_output_flow.effect_count > 1) { + paint_context_.guest_output_intermediate_texture_last_usage = + current_paint_submission; + } + + command_list->SetDescriptorHeaps(1, &view_heap); + } + + // This effect loop must not be aborted so the states of the resources + // involved are consistent. + D3D12_GPU_DESCRIPTOR_HANDLE view_heap_gpu_start = + view_heap->GetGPUDescriptorHandleForHeapStart(); + for (size_t i = 0; i < guest_output_flow.effect_count; ++i) { + bool is_final_effect = i + 1 >= guest_output_flow.effect_count; + + GuestOutputPaintEffect effect = guest_output_flow.effects[i]; + + ID3D12Resource* effect_dest_resource; + int32_t effect_rect_x, effect_rect_y; + if (is_final_effect) { + effect_dest_resource = back_buffer; + if (!back_buffer_acquired) { + D3D12_RESOURCE_BARRIER barrier_present_to_rtv; + barrier_present_to_rtv.Type = + D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_present_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_present_to_rtv.Transition.pResource = back_buffer; + barrier_present_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_present_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PRESENT; + barrier_present_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + command_list->ResourceBarrier(1, &barrier_present_to_rtv); + back_buffer_acquired = true; + } + effect_rect_x = guest_output_flow.output_x; + effect_rect_y = guest_output_flow.output_y; + } else { + effect_dest_resource = + paint_context_.guest_output_intermediate_textures[i].Get(); + if (!i) { + // If this is not the first effect, the transition has been done at + // the end of the previous effect in a single command. + D3D12_RESOURCE_BARRIER barrier_srv_to_rtv; + barrier_srv_to_rtv.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_srv_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_srv_to_rtv.Transition.pResource = effect_dest_resource; + barrier_srv_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_srv_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + barrier_srv_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + command_list->ResourceBarrier(1, &barrier_srv_to_rtv); + } + command_list->DiscardResource(effect_dest_resource, nullptr); + effect_rect_x = 0; + effect_rect_y = 0; + } + + if (is_final_effect) { + if (!back_buffer_bound) { + command_list->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, + nullptr); + back_buffer_bound = true; + } + } else { + D3D12_CPU_DESCRIPTOR_HANDLE intermediate_rtv = + provider_.OffsetRTVDescriptor( + rtv_heap_start, + uint32_t(PaintContext::kRTVIndexGuestOutputIntermediate0 + + i)); + command_list->OMSetRenderTargets(1, &intermediate_rtv, TRUE, nullptr); + back_buffer_bound = false; + } + if (is_final_effect) { + back_buffer_bound = true; + } + D3D12_RESOURCE_DESC effect_dest_resource_desc = + effect_dest_resource->GetDesc(); + D3D12_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = float(effect_dest_resource_desc.Width); + viewport.Height = float(effect_dest_resource_desc.Height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + command_list->RSSetViewports(1, &viewport); + D3D12_RECT scissor; + scissor.left = 0; + scissor.top = 0; + scissor.right = LONG(effect_dest_resource_desc.Width); + scissor.bottom = LONG(effect_dest_resource_desc.Height); + command_list->RSSetScissorRects(1, &scissor); + + command_list->SetPipelineState( + is_final_effect + ? guest_output_paint_final_pipelines_[size_t(effect)].Get() + : guest_output_paint_intermediate_pipelines_[size_t(effect)] + .Get()); + GuestOutputPaintRootSignatureIndex + guest_output_paint_root_signature_index = + GetGuestOutputPaintRootSignatureIndex(effect); + command_list->SetGraphicsRootSignature( + guest_output_paint_root_signatures_ + [size_t(guest_output_paint_root_signature_index)] + .Get()); + + UINT effect_src_view_index = UINT( + i ? (PaintContext::kViewIndexGuestOutputIntermediate0Srv + (i - 1)) + : (PaintContext::kViewIndexGuestOutput0Srv + + guest_output_resource_paint_ref_index)); + command_list->SetGraphicsRootDescriptorTable( + UINT(GuestOutputPaintRootParameter::kSource), + provider_.OffsetViewDescriptor(view_heap_gpu_start, + effect_src_view_index)); + + GuestOutputPaintRectangleConstants effect_rect_constants; + float effect_x_to_ndc = 2.0f / viewport.Width; + float effect_y_to_ndc = 2.0f / viewport.Height; + effect_rect_constants.x = + -1.0f + float(effect_rect_x) * effect_x_to_ndc; + // +Y is -V. + effect_rect_constants.y = 1.0f - float(effect_rect_y) * effect_y_to_ndc; + effect_rect_constants.width = + float(guest_output_flow.effect_output_sizes[i].first) * + effect_x_to_ndc; + effect_rect_constants.height = + -float(guest_output_flow.effect_output_sizes[i].second) * + effect_y_to_ndc; + command_list->SetGraphicsRoot32BitConstants( + UINT(GuestOutputPaintRootParameter::kRectangle), + sizeof(effect_rect_constants) / sizeof(uint32_t), + &effect_rect_constants, 0); + + UINT effect_constants_size = 0; + union { + BilinearConstants bilinear; + CasSharpenConstants cas_sharpen; + CasResampleConstants cas_resample; + FsrEasuConstants fsr_easu; + FsrRcasConstants fsr_rcas; + } effect_constants; + switch (guest_output_paint_root_signature_index) { + case kGuestOutputPaintRootSignatureIndexBilinear: { + effect_constants_size = sizeof(effect_constants.bilinear); + effect_constants.bilinear.Initialize(guest_output_flow, i); + } break; + case kGuestOutputPaintRootSignatureIndexCasSharpen: { + effect_constants_size = sizeof(effect_constants.cas_sharpen); + effect_constants.cas_sharpen.Initialize(guest_output_flow, i, + guest_output_paint_config); + } break; + case kGuestOutputPaintRootSignatureIndexCasResample: { + effect_constants_size = sizeof(effect_constants.cas_resample); + effect_constants.cas_resample.Initialize(guest_output_flow, i, + guest_output_paint_config); + } break; + case kGuestOutputPaintRootSignatureIndexFsrEasu: { + effect_constants_size = sizeof(effect_constants.fsr_easu); + effect_constants.fsr_easu.Initialize(guest_output_flow, i); + } break; + case kGuestOutputPaintRootSignatureIndexFsrRcas: { + effect_constants_size = sizeof(effect_constants.fsr_rcas); + effect_constants.fsr_rcas.Initialize(guest_output_flow, i, + guest_output_paint_config); + } break; + default: + break; + } + if (effect_constants_size) { + command_list->SetGraphicsRoot32BitConstants( + UINT(GuestOutputPaintRootParameter::kEffectConstants), + effect_constants_size / sizeof(uint32_t), &effect_constants, 0); + } + + command_list->IASetPrimitiveTopology( + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + command_list->DrawInstanced(4, 1, 0, 0); + + if (is_final_effect) { + // Clear the letterbox around the guest output if the guest output + // doesn't cover the entire back buffer. + if (guest_output_flow.letterbox_clear_rectangle_count) { + D3D12_RECT letterbox_clear_d3d12_rectangles + [GuestOutputPaintFlow::kMaxClearRectangles]; + for (size_t i = 0; + i < guest_output_flow.letterbox_clear_rectangle_count; ++i) { + D3D12_RECT& letterbox_clear_d3d12_rectangle = + letterbox_clear_d3d12_rectangles[i]; + const GuestOutputPaintFlow::ClearRectangle& + letterbox_clear_rectangle = + guest_output_flow.letterbox_clear_rectangles[i]; + letterbox_clear_d3d12_rectangle.left = + LONG(letterbox_clear_rectangle.x); + letterbox_clear_d3d12_rectangle.top = + LONG(letterbox_clear_rectangle.y); + letterbox_clear_d3d12_rectangle.right = + LONG(letterbox_clear_rectangle.x + + letterbox_clear_rectangle.width); + letterbox_clear_d3d12_rectangle.bottom = + LONG(letterbox_clear_rectangle.y + + letterbox_clear_rectangle.height); + } + command_list->ClearRenderTargetView( + back_buffer_rtv, kBackBufferClearColor, + UINT(guest_output_flow.letterbox_clear_rectangle_count), + letterbox_clear_d3d12_rectangles); + } + back_buffer_clear_needed = false; + } else { + D3D12_RESOURCE_BARRIER barriers[2]; + UINT barrier_count = 0; + // Transition the newly written intermediate image to SRV for use as + // the source in the next effect. + { + assert_true(barrier_count < xe::countof(barriers)); + D3D12_RESOURCE_BARRIER& barrier_rtv_to_srv = + barriers[barrier_count++]; + barrier_rtv_to_srv.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_rtv_to_srv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_rtv_to_srv.Transition.pResource = effect_dest_resource; + barrier_rtv_to_srv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_rtv_to_srv.Transition.StateBefore = + D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier_rtv_to_srv.Transition.StateAfter = + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + } + // Merge the current destination > next source transition with the + // acquisition of the destination for the next effect. + if (i + 2 < guest_output_flow.effect_count) { + // The next effect won't be the last - transition the next + // intermediate destination to RTV. + assert_true(barrier_count < xe::countof(barriers)); + D3D12_RESOURCE_BARRIER& barrier_srv_to_rtv = + barriers[barrier_count++]; + barrier_srv_to_rtv.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_srv_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_srv_to_rtv.Transition.pResource = + paint_context_.guest_output_intermediate_textures[i + 1].Get(); + barrier_srv_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_srv_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + barrier_srv_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + } else { + // The next effect draws to the back buffer - merge into one + // ResourceBarrier command. + if (!back_buffer_acquired) { + assert_true(barrier_count < xe::countof(barriers)); + D3D12_RESOURCE_BARRIER& barrier_present_to_rtv = + barriers[barrier_count++]; + barrier_present_to_rtv.Type = + D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_present_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_present_to_rtv.Transition.pResource = back_buffer; + barrier_present_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_present_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PRESENT; + barrier_present_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + back_buffer_acquired = true; + } + } + if (barrier_count) { + command_list->ResourceBarrier(barrier_count, barriers); + } + } + } + } + } + + // Release main target guest output texture references that aren't needed + // anymore (this is done after various potential guest-output-related main + // target submission tracker waits so the completed submission value is the + // most actual). + UINT64 completed_paint_submission = + paint_context_.paint_submission_tracker.GetCompletedSubmission(); + for (std::pair>& + guest_output_resource_paint_ref : + paint_context_.guest_output_resource_paint_refs) { + if (!guest_output_resource_paint_ref.second || + guest_output_resource_paint_ref.second == guest_output_resource) { + continue; + } + if (completed_paint_submission >= guest_output_resource_paint_ref.first) { + guest_output_resource_paint_ref.second.Reset(); + } + } + + // If no guest output has been drawn, the transitioned of the back buffer to + // RTV hasn't been done yet, and it's needed to clear it, and optionally to + // draw the UI. + if (!back_buffer_acquired) { + D3D12_RESOURCE_BARRIER barrier_present_to_rtv; + barrier_present_to_rtv.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_present_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_present_to_rtv.Transition.pResource = back_buffer; + barrier_present_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_present_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PRESENT; + barrier_present_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + command_list->ResourceBarrier(1, &barrier_present_to_rtv); + back_buffer_acquired = true; + } + + if (back_buffer_clear_needed) { + command_list->ClearRenderTargetView(back_buffer_rtv, kBackBufferClearColor, + 0, nullptr); + back_buffer_clear_needed = false; + } + + if (execute_ui_drawers) { + // Draw the UI. + if (!back_buffer_bound) { + command_list->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr); + back_buffer_bound = true; + } + D3D12UIDrawContext ui_draw_context( + *this, paint_context_.swap_chain_width, + paint_context_.swap_chain_height, command_list, + ui_submission_tracker_.GetCurrentSubmission(), + ui_submission_tracker_.GetCompletedSubmission()); + ExecuteUIDrawersFromUIThread(ui_draw_context); + } + + // End drawing to the back buffer. + D3D12_RESOURCE_BARRIER barrier_rtv_to_present; + barrier_rtv_to_present.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_rtv_to_present.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_rtv_to_present.Transition.pResource = back_buffer; + barrier_rtv_to_present.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_rtv_to_present.Transition.StateBefore = + D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier_rtv_to_present.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + command_list->ResourceBarrier(1, &barrier_rtv_to_present); + + // Execute and present. + command_list->Close(); + ID3D12CommandList* execute_command_list = command_list; + provider_.GetDirectQueue()->ExecuteCommandLists(1, &execute_command_list); + if (execute_ui_drawers) { + ui_submission_tracker_.NextSubmission(); + } + paint_context_.paint_submission_tracker.NextSubmission(); + // Present as soon as possible, without waiting for vsync (the host refresh + // rate may be something like 144 Hz, which is not a multiple of the common + // 30 Hz or 60 Hz guest refresh rate), and allowing dropping outdated queued + // frames for lower latency. Also, if possible, allowing tearing to use + // variable refresh rate in borderless fullscreen (note that if DXGI + // fullscreen is ever used in, the allow tearing flag must not be passed in + // fullscreen, but DXGI fullscreen is largely unneeded with the flip + // presentation model used in Direct3D 12). + HRESULT present_result = paint_context_.swap_chain->Present( + 0, DXGI_PRESENT_RESTART | (paint_context_.swap_chain_allows_tearing + ? DXGI_PRESENT_ALLOW_TEARING + : 0)); + // Even if presentation has failed, work might have been enqueued anyway + // internally before the failure according to Jesse Natalie from the DirectX + // Discord server. + paint_context_.present_submission_tracker.NextSubmission(); + switch (present_result) { + case DXGI_ERROR_DEVICE_REMOVED: + return PaintResult::kGpuLostExternally; + case DXGI_ERROR_DEVICE_RESET: + return PaintResult::kGpuLostResponsible; + default: + return SUCCEEDED(present_result) ? PaintResult::kPresented + : PaintResult::kNotPresented; + } +} + +bool D3D12Presenter::InitializeSurfaceIndependent() { + // Check if DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING is supported. + { + Microsoft::WRL::ComPtr dxgi_factory_5; + if (SUCCEEDED(provider_.GetDXGIFactory()->QueryInterface( + IID_PPV_ARGS(&dxgi_factory_5)))) { + BOOL tearing_feature_data; + dxgi_supports_tearing_ = + SUCCEEDED(dxgi_factory_5->CheckFeatureSupport( + DXGI_FEATURE_PRESENT_ALLOW_TEARING, &tearing_feature_data, + sizeof(tearing_feature_data))) && + tearing_feature_data; + } + } + + ID3D12Device* device = provider_.GetDevice(); + + // Initialize static guest output painting objects. + + // Guest output painting root signatures. + // One (texture) for bilinear, two (texture and constants) for AMD FidelityFX + // CAS and FSR. + D3D12_ROOT_PARAMETER guest_output_paint_root_parameters[UINT( + GuestOutputPaintRootParameter::kCount)]; + // Source texture. + D3D12_DESCRIPTOR_RANGE guest_output_paint_root_descriptor_range_source; + guest_output_paint_root_descriptor_range_source.RangeType = + D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + guest_output_paint_root_descriptor_range_source.NumDescriptors = 1; + guest_output_paint_root_descriptor_range_source.BaseShaderRegister = 0; + guest_output_paint_root_descriptor_range_source.RegisterSpace = 0; + guest_output_paint_root_descriptor_range_source + .OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& guest_output_paint_root_parameter_source = + guest_output_paint_root_parameters[UINT( + GuestOutputPaintRootParameter::kSource)]; + guest_output_paint_root_parameter_source.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + guest_output_paint_root_parameter_source.DescriptorTable + .NumDescriptorRanges = 1; + guest_output_paint_root_parameter_source.DescriptorTable.pDescriptorRanges = + &guest_output_paint_root_descriptor_range_source; + guest_output_paint_root_parameter_source.ShaderVisibility = + D3D12_SHADER_VISIBILITY_PIXEL; + } + // Rectangle. + { + D3D12_ROOT_PARAMETER& guest_output_paint_root_parameter_rect = + guest_output_paint_root_parameters[UINT( + GuestOutputPaintRootParameter::kRectangle)]; + guest_output_paint_root_parameter_rect.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + guest_output_paint_root_parameter_rect.Constants.ShaderRegister = 0; + guest_output_paint_root_parameter_rect.Constants.RegisterSpace = 0; + guest_output_paint_root_parameter_rect.Constants.Num32BitValues = + sizeof(GuestOutputPaintRectangleConstants) / sizeof(uint32_t); + guest_output_paint_root_parameter_rect.ShaderVisibility = + D3D12_SHADER_VISIBILITY_VERTEX; + } + // Pixel shader constants. + D3D12_ROOT_PARAMETER& guest_output_paint_root_parameter_effect_constants = + guest_output_paint_root_parameters[UINT( + GuestOutputPaintRootParameter::kEffectConstants)]; + guest_output_paint_root_parameter_effect_constants.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + guest_output_paint_root_parameter_effect_constants.Constants.ShaderRegister = + 0; + guest_output_paint_root_parameter_effect_constants.Constants.RegisterSpace = + 0; + guest_output_paint_root_parameter_effect_constants.ShaderVisibility = + D3D12_SHADER_VISIBILITY_PIXEL; + // Bilinear sampler. + D3D12_STATIC_SAMPLER_DESC guest_output_paint_root_sampler; + guest_output_paint_root_sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + guest_output_paint_root_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + guest_output_paint_root_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + guest_output_paint_root_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + guest_output_paint_root_sampler.MipLODBias = 0.0f; + guest_output_paint_root_sampler.MaxAnisotropy = 1; + guest_output_paint_root_sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + guest_output_paint_root_sampler.BorderColor = + D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + guest_output_paint_root_sampler.MinLOD = 0.0f; + guest_output_paint_root_sampler.MaxLOD = 0.0f; + guest_output_paint_root_sampler.ShaderRegister = 0; + guest_output_paint_root_sampler.RegisterSpace = 0; + guest_output_paint_root_sampler.ShaderVisibility = + D3D12_SHADER_VISIBILITY_PIXEL; + D3D12_ROOT_SIGNATURE_DESC guest_output_paint_root_signature_desc; + guest_output_paint_root_signature_desc.NumParameters = + UINT(GuestOutputPaintRootParameter::kCount); + guest_output_paint_root_signature_desc.pParameters = + guest_output_paint_root_parameters; + guest_output_paint_root_signature_desc.NumStaticSamplers = 1; + guest_output_paint_root_signature_desc.pStaticSamplers = + &guest_output_paint_root_sampler; + guest_output_paint_root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + // Bilinear filtering (needs the sampler). + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(BilinearConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output bilinear " + "filtering presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexBilinear] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + // EASU (needs the sampler). + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(FsrEasuConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output AMD FidelityFX " + "FSR EASU presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexFsrEasu] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + // RCAS and CAS don't need the sampler. + guest_output_paint_root_signature_desc.NumStaticSamplers = 0; + // RCAS. + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(FsrRcasConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output AMD FidelityFX " + "FSR RCAS presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexFsrRcas] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + // CAS, sharpening only. + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(CasSharpenConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output AMD FidelityFX " + "CAS presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexCasSharpen] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + // CAS, resampling. + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(CasResampleConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output resampling AMD " + "FidelityFX CAS presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexCasResample] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + + // Guest output painting pipelines. + D3D12_GRAPHICS_PIPELINE_STATE_DESC guest_output_paint_pipeline_desc = {}; + guest_output_paint_pipeline_desc.VS.pShaderBytecode = + shaders::guest_output_triangle_strip_rect_vs; + guest_output_paint_pipeline_desc.VS.BytecodeLength = + sizeof(shaders::guest_output_triangle_strip_rect_vs); + guest_output_paint_pipeline_desc.BlendState.RenderTarget[0] + .RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + guest_output_paint_pipeline_desc.SampleMask = UINT_MAX; + guest_output_paint_pipeline_desc.RasterizerState.FillMode = + D3D12_FILL_MODE_SOLID; + guest_output_paint_pipeline_desc.RasterizerState.CullMode = + D3D12_CULL_MODE_NONE; + guest_output_paint_pipeline_desc.RasterizerState.DepthClipEnable = TRUE; + guest_output_paint_pipeline_desc.PrimitiveTopologyType = + D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + guest_output_paint_pipeline_desc.NumRenderTargets = 1; + guest_output_paint_pipeline_desc.SampleDesc.Count = 1; + for (size_t i = 0; i < size_t(GuestOutputPaintEffect::kCount); ++i) { + GuestOutputPaintEffect guest_output_paint_effect = + GuestOutputPaintEffect(i); + switch (guest_output_paint_effect) { + case GuestOutputPaintEffect::kBilinear: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_bilinear_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_bilinear_ps); + break; + case GuestOutputPaintEffect::kBilinearDither: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_bilinear_dither_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_bilinear_dither_ps); + break; + case GuestOutputPaintEffect::kCasSharpen: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_cas_sharpen_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_cas_sharpen_ps); + break; + case GuestOutputPaintEffect::kCasSharpenDither: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_cas_sharpen_dither_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_cas_sharpen_dither_ps); + break; + case GuestOutputPaintEffect::kCasResample: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_cas_resample_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_cas_resample_ps); + break; + case GuestOutputPaintEffect::kCasResampleDither: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_cas_resample_dither_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_cas_resample_dither_ps); + break; + case GuestOutputPaintEffect::kFsrEasu: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_fsr_easu_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_fsr_easu_ps); + break; + case GuestOutputPaintEffect::kFsrRcas: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_fsr_rcas_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_fsr_rcas_ps); + break; + case GuestOutputPaintEffect::kFsrRcasDither: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_fsr_rcas_dither_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_fsr_rcas_dither_ps); + break; + default: + // Not supported by this implementation. + continue; + } + guest_output_paint_pipeline_desc.pRootSignature = + guest_output_paint_root_signatures_ + [GetGuestOutputPaintRootSignatureIndex(guest_output_paint_effect)] + .Get(); + if (CanGuestOutputPaintEffectBeIntermediate(guest_output_paint_effect)) { + guest_output_paint_pipeline_desc.RTVFormats[0] = + kGuestOutputIntermediateFormat; + if (FAILED(device->CreateGraphicsPipelineState( + &guest_output_paint_pipeline_desc, + IID_PPV_ARGS(&guest_output_paint_intermediate_pipelines_[i])))) { + XELOGE( + "D3D12Presenter: Failed to create the guest output painting " + "pipeline for effect {} writing to an intermediate texture", + i); + return false; + } + } + if (CanGuestOutputPaintEffectBeFinal(guest_output_paint_effect)) { + guest_output_paint_pipeline_desc.RTVFormats[0] = kSwapChainFormat; + if (FAILED(device->CreateGraphicsPipelineState( + &guest_output_paint_pipeline_desc, + IID_PPV_ARGS(&guest_output_paint_final_pipelines_[i])))) { + XELOGE( + "D3D12Presenter: Failed to create the guest output painting " + "pipeline for effect {} writing to a swap chain buffer", + i); + return false; + } + } + } + + // Initialize connection-independent parts of the painting context. + + ID3D12CommandQueue* direct_queue = provider_.GetDirectQueue(); + + // Paint submission trackers. + if (!paint_context_.paint_submission_tracker.Initialize(device, + direct_queue) || + !paint_context_.present_submission_tracker.Initialize(device, + direct_queue)) { + return false; + } + + // Paint command allocators and command list. + for (Microsoft::WRL::ComPtr& + paint_command_allocator_ref : paint_context_.command_allocators) { + if (FAILED(device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&paint_command_allocator_ref)))) { + XELOGE( + "D3D12Presenter: Failed to create a command allocator for drawing to " + "a swap chain"); + return false; + } + } + if (FAILED(device->CreateCommandList( + 0, D3D12_COMMAND_LIST_TYPE_DIRECT, + paint_context_.command_allocators[0].Get(), nullptr, + IID_PPV_ARGS(&paint_context_.command_list)))) { + XELOGE( + "D3D12Presenter: Failed to create the command list for drawing to a " + "swap chain"); + return false; + } + // Command lists are created in an open state. + paint_context_.command_list->Close(); + + // RTV descriptor heap. + D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc; + rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtv_heap_desc.NumDescriptors = PaintContext::kRTVCount; + rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + rtv_heap_desc.NodeMask = 0; + if (FAILED(device->CreateDescriptorHeap( + &rtv_heap_desc, IID_PPV_ARGS(&paint_context_.rtv_heap)))) { + XELOGE( + "D3D12Presenter: Failed to create an RTV descriptor heap with {} " + "descriptors", + rtv_heap_desc.NumDescriptors); + return false; + } + + // CBV/SRV/UAV descriptor heap. + D3D12_DESCRIPTOR_HEAP_DESC view_heap_desc; + view_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + view_heap_desc.NumDescriptors = PaintContext::kViewCount; + view_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + view_heap_desc.NodeMask = 0; + if (FAILED(device->CreateDescriptorHeap( + &view_heap_desc, IID_PPV_ARGS(&paint_context_.view_heap)))) { + XELOGE( + "D3D12Presenter: Failed to create a shader-visible CBV/SRV/UAV " + "descriptor heap with {} descriptors", + view_heap_desc.NumDescriptors); + return false; + } + + if (!guest_output_resource_refresher_submission_tracker_.Initialize( + device, direct_queue)) { + return false; + } + + if (!ui_submission_tracker_.Initialize(device, direct_queue)) { + return false; + } + + return InitializeCommonSurfaceIndependent(); +} + +} // namespace d3d12 +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/d3d12/d3d12_presenter.h b/src/xenia/ui/d3d12/d3d12_presenter.h new file mode 100644 index 000000000..81d9c4ff5 --- /dev/null +++ b/src/xenia/ui/d3d12/d3d12_presenter.h @@ -0,0 +1,332 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_D3D12_D3D12_PRESENTER_H_ +#define XENIA_UI_D3D12_D3D12_PRESENTER_H_ + +#include +#include +#include + +#include "xenia/base/math.h" +#include "xenia/ui/d3d12/d3d12_provider.h" +#include "xenia/ui/d3d12/d3d12_submission_tracker.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/surface.h" + +namespace xe { +namespace ui { +namespace d3d12 { + +class D3D12UIDrawContext final : public UIDrawContext { + public: + D3D12UIDrawContext(Presenter& presenter, uint32_t render_target_width, + uint32_t render_target_height, + ID3D12GraphicsCommandList* command_list, + UINT64 submission_index_current, + UINT64 submission_index_completed) + : UIDrawContext(presenter, render_target_width, render_target_height), + command_list_(command_list), + submission_index_current_(submission_index_current), + submission_index_completed_(submission_index_completed) {} + + ID3D12GraphicsCommandList* command_list() const { + return command_list_.Get(); + } + UINT64 submission_index_current() const { return submission_index_current_; } + UINT64 submission_index_completed() const { + return submission_index_completed_; + } + + private: + Microsoft::WRL::ComPtr command_list_; + UINT64 submission_index_current_; + UINT64 submission_index_completed_; +}; + +class D3D12Presenter final : public Presenter { + public: + static constexpr DXGI_FORMAT kGuestOutputFormat = + DXGI_FORMAT_R10G10B10A2_UNORM; + static constexpr D3D12_RESOURCE_STATES kGuestOutputInternalState = + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + + static constexpr DXGI_FORMAT kGuestOutputIntermediateFormat = + DXGI_FORMAT_R10G10B10A2_UNORM; + + // The format used internally by Windows composition. + static constexpr DXGI_FORMAT kSwapChainFormat = DXGI_FORMAT_B8G8R8A8_UNORM; + + // The callback must use the main direct queue of the provider. + class D3D12GuestOutputRefreshContext final + : public GuestOutputRefreshContext { + public: + D3D12GuestOutputRefreshContext(bool& is_8bpc_out_ref, + ID3D12Resource* resource) + : GuestOutputRefreshContext(is_8bpc_out_ref), resource_(resource) {} + + // kGuestOutputFormat, supports UAV. The initial state in the callback is + // kGuestOutputInternalState, and the callback must also transition it back + // to kGuestOutputInternalState before finishing. + ID3D12Resource* resource_uav_capable() const { return resource_.Get(); } + + private: + Microsoft::WRL::ComPtr resource_; + }; + + static std::unique_ptr Create( + HostGpuLossCallback host_gpu_loss_callback, + const D3D12Provider& provider) { + auto presenter = std::unique_ptr( + new D3D12Presenter(host_gpu_loss_callback, provider)); + if (!presenter->InitializeSurfaceIndependent()) { + return nullptr; + } + return presenter; + } + + ~D3D12Presenter(); + + const D3D12Provider& provider() const { return provider_; } + + Surface::TypeFlags GetSupportedSurfaceTypes() const override; + + bool CaptureGuestOutput(RawImage& image_out) override; + + void AwaitUISubmissionCompletionFromUIThread(UINT64 submission_index) { + ui_submission_tracker_.AwaitSubmissionCompletion(submission_index); + } + + protected: + SurfacePaintConnectResult ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) override; + void DisconnectPaintingFromSurfaceFromUIThreadImpl() override; + + bool RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out) override; + + PaintResult PaintAndPresentImpl(bool execute_ui_drawers) override; + + private: + struct GuestOutputPaintRectangleConstants { + union { + struct { + float x; + float y; + }; + float offset[2]; + }; + union { + struct { + float width; + float height; + }; + float size[2]; + }; + }; + + enum class GuestOutputPaintRootParameter : UINT { + kSource, + kRectangle, + kEffectConstants, + + kCount, + }; + + enum GuestOutputPaintRootSignatureIndex : size_t { + kGuestOutputPaintRootSignatureIndexBilinear, + kGuestOutputPaintRootSignatureIndexCasSharpen, + kGuestOutputPaintRootSignatureIndexCasResample, + kGuestOutputPaintRootSignatureIndexFsrEasu, + kGuestOutputPaintRootSignatureIndexFsrRcas, + + kGuestOutputPaintRootSignatureCount, + }; + + static constexpr GuestOutputPaintRootSignatureIndex + GetGuestOutputPaintRootSignatureIndex(GuestOutputPaintEffect effect) { + switch (effect) { + case GuestOutputPaintEffect::kBilinear: + case GuestOutputPaintEffect::kBilinearDither: + return kGuestOutputPaintRootSignatureIndexBilinear; + case GuestOutputPaintEffect::kCasSharpen: + case GuestOutputPaintEffect::kCasSharpenDither: + return kGuestOutputPaintRootSignatureIndexCasSharpen; + case GuestOutputPaintEffect::kCasResample: + case GuestOutputPaintEffect::kCasResampleDither: + return kGuestOutputPaintRootSignatureIndexCasResample; + case GuestOutputPaintEffect::kFsrEasu: + return kGuestOutputPaintRootSignatureIndexFsrEasu; + case GuestOutputPaintEffect::kFsrRcas: + case GuestOutputPaintEffect::kFsrRcasDither: + return kGuestOutputPaintRootSignatureIndexFsrRcas; + default: + assert_unhandled_case(effect); + return kGuestOutputPaintRootSignatureCount; + } + } + + struct PaintContext { + explicit PaintContext() = default; + PaintContext(const PaintContext& paint_context) = delete; + PaintContext& operator=(const PaintContext& paint_context) = delete; + + static constexpr uint32_t kSwapChainBufferCount = 3; + + enum RTVIndex : UINT { + // Swap chain buffers - updated when creating the swap chain + // (connection-specific). + kRTVIndexSwapChainBuffer0, + + // Intermediate textures - the last usage is + // guest_output_intermediate_texture_paint_last_usage_. + kRTVIndexGuestOutputIntermediate0 = + kRTVIndexSwapChainBuffer0 + kSwapChainBufferCount, + + kRTVCount = + kRTVIndexGuestOutputIntermediate0 + kGuestOutputMailboxSize - 1, + }; + + enum ViewIndex : UINT { + // Guest output textures - indices are the same as in + // guest_output_resource_paint_refs, and the last usage is tied to them. + kViewIndexGuestOutput0Srv, + + // Intermediate textures - the last usage is + // guest_output_intermediate_texture_paint_last_usage_. + kViewIndexGuestOutputIntermediate0Srv = + kViewIndexGuestOutput0Srv + kGuestOutputMailboxSize, + + kViewCount = kViewIndexGuestOutputIntermediate0Srv + + kMaxGuestOutputPaintEffects - 1, + }; + + void AwaitSwapChainUsageCompletion() { + // Presentation engine usage. + present_submission_tracker.AwaitAllSubmissionsCompletion(); + // Paint (render target) usage. While the presentation fence is signaled + // on the same queue, and presentation happens after painting, awaiting + // anyway for safety just to make less assumptions in the architecture. + paint_submission_tracker.AwaitAllSubmissionsCompletion(); + } + + void DestroySwapChain(); + + // Connection-independent. + + // Signaled before presenting. + D3D12SubmissionTracker paint_submission_tracker; + // Signaled after presenting. + D3D12SubmissionTracker present_submission_tracker; + + std::array, + kSwapChainBufferCount> + command_allocators; + Microsoft::WRL::ComPtr command_list; + + // Descriptor heaps for views of the current resources related to the guest + // output and to painting, updated either during painting or during + // connection lifetime management if outdated after awaiting usage + // completion. + // RTV heap. + Microsoft::WRL::ComPtr rtv_heap; + // Shader-visible CBV/SRV/UAV heap. + Microsoft::WRL::ComPtr view_heap; + + // Refreshed and cleaned up during guest output painting. The first is the + // paint submission index in which the guest output texture (and its + // descriptors) was last used, the second is the reference to the texture, + // which may be null. The indices are not mailbox indices here, rather, if + // the reference is not in this array yet, the most outdated reference, if + // needed, is replaced with the new one, awaiting the completion of the last + // paint usage. + std::array>, + kGuestOutputMailboxSize> + guest_output_resource_paint_refs; + + // Current intermediate textures for guest output painting, refreshed when + // painting guest output. While not in use, they are in + // D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE. + std::array, + kMaxGuestOutputPaintEffects - 1> + guest_output_intermediate_textures; + UINT64 guest_output_intermediate_texture_last_usage = 0; + + // Connection-specific. + + uint32_t swap_chain_width = 0; + uint32_t swap_chain_height = 0; + bool swap_chain_allows_tearing = false; + Microsoft::WRL::ComPtr swap_chain; + std::array, kSwapChainBufferCount> + swap_chain_buffers; + }; + + explicit D3D12Presenter(HostGpuLossCallback host_gpu_loss_callback, + const D3D12Provider& provider) + : Presenter(host_gpu_loss_callback), provider_(provider) {} + + bool dxgi_supports_tearing() const { return dxgi_supports_tearing_; } + + bool InitializeSurfaceIndependent(); + + const D3D12Provider& provider_; + + // Whether DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING is supported by DXGI (depends in + // particular on the Windows 10 version and hardware support), primarily for + // variable refresh rate support. + bool dxgi_supports_tearing_ = false; + + // Static objects for guest output presentation, used only when painting the + // main target (can be destroyed only after awaiting main target usage + // completion). + std::array, + kGuestOutputPaintRootSignatureCount> + guest_output_paint_root_signatures_; + std::array, + size_t(GuestOutputPaintEffect::kCount)> + guest_output_paint_intermediate_pipelines_; + std::array, + size_t(GuestOutputPaintEffect::kCount)> + guest_output_paint_final_pipelines_; + + // The first is the refresher submission tracker fence value at which the + // guest output texture was last refreshed, the second is the reference to the + // texture, which may be null. The indices are the mailbox indices. + std::array>, + kGuestOutputMailboxSize> + guest_output_resources_; + // The guest output resources are protected by two submission trackers - the + // refresher ones (for writing to them via the guest_output_resources_ + // references) and the paint one (for presenting it via the + // paint_context_.guest_output_resource_paint_refs references taken from + // guest_output_resources_). + D3D12SubmissionTracker guest_output_resource_refresher_submission_tracker_; + + // UI submission tracker with the submission index that can be given to UI + // drawers (accessible from the UI thread only, at any time). + D3D12SubmissionTracker ui_submission_tracker_; + + // Accessible only by painting and by surface connection lifetime management + // (ConnectOrReconnectPaintingToSurfaceFromUIThread, + // DisconnectPaintingFromSurfaceFromUIThreadImpl) by the thread doing it, as + // well as by presenter initialization and shutdown. + PaintContext paint_context_; +}; + +} // namespace d3d12 +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_D3D12_D3D12_PRESENTER_H_ diff --git a/src/xenia/ui/d3d12/d3d12_provider.cc b/src/xenia/ui/d3d12/d3d12_provider.cc index 32e9d4bef..3c3825091 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.cc +++ b/src/xenia/ui/d3d12/d3d12_provider.cc @@ -15,7 +15,8 @@ #include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" -#include "xenia/ui/d3d12/d3d12_context.h" +#include "xenia/ui/d3d12/d3d12_immediate_drawer.h" +#include "xenia/ui/d3d12/d3d12_presenter.h" DEFINE_bool(d3d12_debug, false, "Enable Direct3D 12 and DXGI debug layer.", "D3D12"); @@ -77,6 +78,14 @@ D3D12Provider::~D3D12Provider() { dxgi_factory_->Release(); } + if (cvars::d3d12_debug && pfn_dxgi_get_debug_interface1_) { + Microsoft::WRL::ComPtr dxgi_debug; + if (SUCCEEDED( + pfn_dxgi_get_debug_interface1_(0, IID_PPV_ARGS(&dxgi_debug)))) { + dxgi_debug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL); + } + } + if (library_dxcompiler_ != nullptr) { FreeLibrary(library_dxcompiler_); } @@ -86,9 +95,6 @@ D3D12Provider::~D3D12Provider() { if (library_d3dcompiler_ != nullptr) { FreeLibrary(library_d3dcompiler_); } - if (library_dcomp_ != nullptr) { - FreeLibrary(library_dcomp_); - } if (library_d3d12_ != nullptr) { FreeLibrary(library_d3d12_); } @@ -120,9 +126,8 @@ bool D3D12Provider::Initialize() { // Load the core libraries. library_dxgi_ = LoadLibraryW(L"dxgi.dll"); library_d3d12_ = LoadLibraryW(L"D3D12.dll"); - library_dcomp_ = LoadLibraryW(L"dcomp.dll"); - if (!library_dxgi_ || !library_d3d12_ || !library_dcomp_) { - XELOGE("Failed to load dxgi.dll, D3D12.dll or dcomp.dll"); + if (!library_dxgi_ || !library_d3d12_) { + XELOGE("Failed to load dxgi.dll or D3D12.dll"); return false; } bool libraries_loaded = true; @@ -143,12 +148,8 @@ bool D3D12Provider::Initialize() { (pfn_d3d12_serialize_root_signature_ = PFN_D3D12_SERIALIZE_ROOT_SIGNATURE( GetProcAddress(library_d3d12_, "D3D12SerializeRootSignature"))) != nullptr; - libraries_loaded &= - (pfn_dcomposition_create_device_ = PFNDCompositionCreateDevice( - GetProcAddress(library_dcomp_, "DCompositionCreateDevice"))) != - nullptr; if (!libraries_loaded) { - XELOGE("Failed to get DXGI, Direct3D 12 or DirectComposition functions"); + XELOGE("Failed to get DXGI or Direct3D 12 functions"); return false; } @@ -470,23 +471,13 @@ bool D3D12Provider::Initialize() { return true; } -std::unique_ptr D3D12Provider::CreateHostContext( - Window* target_window) { - auto new_context = - std::unique_ptr(new D3D12Context(this, target_window)); - if (!new_context->Initialize()) { - return nullptr; - } - return std::unique_ptr(new_context.release()); +std::unique_ptr D3D12Provider::CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback) { + return D3D12Presenter::Create(host_gpu_loss_callback, *this); } -std::unique_ptr D3D12Provider::CreateEmulationContext() { - auto new_context = - std::unique_ptr(new D3D12Context(this, nullptr)); - if (!new_context->Initialize()) { - return nullptr; - } - return std::unique_ptr(new_context.release()); +std::unique_ptr D3D12Provider::CreateImmediateDrawer() { + return D3D12ImmediateDrawer::Create(*this); } } // namespace d3d12 diff --git a/src/xenia/ui/d3d12/d3d12_provider.h b/src/xenia/ui/d3d12/d3d12_provider.h index dca7ad408..937acaae9 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.h +++ b/src/xenia/ui/d3d12/d3d12_provider.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -23,15 +23,17 @@ namespace d3d12 { class D3D12Provider : public GraphicsProvider { public: - ~D3D12Provider() override; + ~D3D12Provider(); static bool IsD3D12APIAvailable(); static std::unique_ptr Create(); - std::unique_ptr CreateHostContext( - Window* target_window) override; - std::unique_ptr CreateEmulationContext() override; + std::unique_ptr CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback = + Presenter::FatalErrorHostGpuLossCallback) override; + + std::unique_ptr CreateImmediateDrawer() override; IDXGIFactory2* GetDXGIFactory() const { return dxgi_factory_; } // nullptr if PIX not attached. @@ -118,11 +120,6 @@ class D3D12Provider : public GraphicsProvider { return pfn_d3d12_serialize_root_signature_(desc, version, blob_out, error_blob_out); } - HRESULT CreateDCompositionDevice(IDXGIDevice* dxgi_device, const IID& iid, - void** dcomposition_device_out) const { - return pfn_dcomposition_create_device_(dxgi_device, iid, - dcomposition_device_out); - } HRESULT Disassemble(const void* src_data, size_t src_data_size, UINT flags, const char* comments, ID3DBlob** disassembly_out) const { if (!pfn_d3d_disassemble_) { @@ -156,22 +153,17 @@ class D3D12Provider : public GraphicsProvider { _COM_Outptr_ void** ppFactory); typedef HRESULT(WINAPI* PFNDXGIGetDebugInterface1)( UINT Flags, REFIID riid, _COM_Outptr_ void** pDebug); - typedef HRESULT(WINAPI* PFNDCompositionCreateDevice)( - _In_opt_ IDXGIDevice* dxgiDevice, _In_ REFIID iid, - _Outptr_ void** dcompositionDevice); HMODULE library_dxgi_ = nullptr; PFNCreateDXGIFactory2 pfn_create_dxgi_factory2_; - PFNDXGIGetDebugInterface1 pfn_dxgi_get_debug_interface1_; + // Needed during shutdown as well to report live objects, so may be nullptr. + PFNDXGIGetDebugInterface1 pfn_dxgi_get_debug_interface1_ = nullptr; HMODULE library_d3d12_ = nullptr; PFN_D3D12_GET_DEBUG_INTERFACE pfn_d3d12_get_debug_interface_; PFN_D3D12_CREATE_DEVICE pfn_d3d12_create_device_; PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfn_d3d12_serialize_root_signature_; - HMODULE library_dcomp_ = nullptr; - PFNDCompositionCreateDevice pfn_dcomposition_create_device_; - HMODULE library_d3dcompiler_ = nullptr; pD3DDisassemble pfn_d3d_disassemble_ = nullptr; @@ -182,9 +174,9 @@ class D3D12Provider : public GraphicsProvider { DxcCreateInstanceProc pfn_dxcompiler_dxc_create_instance_ = nullptr; IDXGIFactory2* dxgi_factory_ = nullptr; - IDXGraphicsAnalysis* graphics_analysis_ = nullptr; ID3D12Device* device_ = nullptr; ID3D12CommandQueue* direct_queue_ = nullptr; + IDXGraphicsAnalysis* graphics_analysis_ = nullptr; uint32_t descriptor_sizes_[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; diff --git a/src/xenia/ui/d3d12/d3d12_submission_tracker.cc b/src/xenia/ui/d3d12/d3d12_submission_tracker.cc new file mode 100644 index 000000000..d8f604f7f --- /dev/null +++ b/src/xenia/ui/d3d12/d3d12_submission_tracker.cc @@ -0,0 +1,126 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/d3d12/d3d12_submission_tracker.h" + +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" + +namespace xe { +namespace ui { +namespace d3d12 { + +bool D3D12SubmissionTracker::Initialize(ID3D12Device* device, + ID3D12CommandQueue* queue) { + Shutdown(); + fence_completion_event_ = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (!fence_completion_event_) { + XELOGE( + "D3D12SubmissionTracker: Failed to create the fence completion event"); + Shutdown(); + return false; + } + // Continue where the tracker was left at the last shutdown. + if (FAILED(device->CreateFence(submission_current_ - 1, D3D12_FENCE_FLAG_NONE, + IID_PPV_ARGS(&fence_)))) { + XELOGE("D3D12SubmissionTracker: Failed to create the fence"); + Shutdown(); + return false; + } + queue_ = queue; + submission_signal_queued_ = submission_current_ - 1; + return true; +} + +void D3D12SubmissionTracker::Shutdown() { + AwaitAllSubmissionsCompletion(); + queue_.Reset(); + fence_.Reset(); + if (fence_completion_event_) { + CloseHandle(fence_completion_event_); + fence_completion_event_ = nullptr; + } +} + +bool D3D12SubmissionTracker::AwaitSubmissionCompletion( + UINT64 submission_index) { + if (!fence_ || !fence_completion_event_) { + // Not fully initialized yet or already shut down. + return false; + } + // The tracker itself can't give a submission index for a submission that + // hasn't even started being recorded yet, the client has provided a + // completely invalid value or has done overly optimistic math if such an + // index has been obtained somehow. + assert_true(submission_index <= submission_current_); + // Waiting for the current submission is fine if there was a refusal to + // submit, and the submission index wasn't incremented, but still need to + // release objects referenced in the dropped submission (while shutting down, + // for instance - in this case, waiting for the last successful submission, + // which could have also referenced the objects from the new submission - we + // can't know since the client has already overwritten its last usage index, + // would correctly ensure that GPU usage of the objects is not pending). + // Waiting for successful submissions, but failed signals, will result in a + // true race condition, however, but waiting for the closest successful signal + // is the best approximation - also retrying to signal in this case. + UINT64 fence_value = submission_index; + if (submission_index > submission_signal_queued_) { + TrySignalEnqueueing(); + fence_value = submission_signal_queued_; + } + if (fence_->GetCompletedValue() < fence_value) { + if (FAILED(fence_->SetEventOnCompletion(fence_value, + fence_completion_event_))) { + return false; + } + if (WaitForSingleObject(fence_completion_event_, INFINITE) != + WAIT_OBJECT_0) { + return false; + } + } + return fence_value == submission_index; +} + +void D3D12SubmissionTracker::SetQueue(ID3D12CommandQueue* new_queue) { + if (queue_.Get() == new_queue) { + return; + } + if (queue_) { + // Make sure the first signal on the new queue won't happen before the last + // signal, if pending, on the old one, as that would result first in too + // early submission completion indication, and then in rewinding. + AwaitAllSubmissionsCompletion(); + } + queue_ = new_queue; +} + +bool D3D12SubmissionTracker::NextSubmission() { + ++submission_current_; + assert_not_null(queue_); + assert_not_null(fence_); + return TrySignalEnqueueing(); +} + +bool D3D12SubmissionTracker::TrySignalEnqueueing() { + if (submission_signal_queued_ + 1 >= submission_current_) { + return true; + } + if (!queue_ || !fence_) { + return false; + } + if (FAILED(queue_->Signal(fence_.Get(), submission_current_ - 1))) { + return false; + } + submission_signal_queued_ = submission_current_ - 1; + return true; +} + +} // namespace d3d12 +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/d3d12/d3d12_submission_tracker.h b/src/xenia/ui/d3d12/d3d12_submission_tracker.h new file mode 100644 index 000000000..cf4e92836 --- /dev/null +++ b/src/xenia/ui/d3d12/d3d12_submission_tracker.h @@ -0,0 +1,93 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_D3D12_D3D12_SUBMISSION_TRACKER_H_ +#define XENIA_UI_D3D12_D3D12_SUBMISSION_TRACKER_H_ + +#include "xenia/ui/d3d12/d3d12_api.h" + +namespace xe { +namespace ui { +namespace d3d12 { + +// GPU > CPU fence wrapper, safely handling cases when the fence has not been +// initialized yet or has already been shut down, dropped submissions, and also +// transfers between queues so signals stay ordered. +// +// The current submission index can be associated with the usage of objects to +// release them when the GPU isn't potentially referencing them anymore, and +// should be incremented only +// +// 0 can be used as a "never referenced" submission index. +// +// The submission index timeline survives Shutdown / Initialize, so submission +// indices can be given to clients that are not aware of the lifetime of the +// tracker. +class D3D12SubmissionTracker { + public: + D3D12SubmissionTracker() = default; + D3D12SubmissionTracker(const D3D12SubmissionTracker& submission_tracker) = + delete; + D3D12SubmissionTracker& operator=( + const D3D12SubmissionTracker& submission_tracker) = delete; + ~D3D12SubmissionTracker() { Shutdown(); } + + // The queue may be null if it's going to be set dynamically. Will also take a + // reference to the queue. + bool Initialize(ID3D12Device* device, ID3D12CommandQueue* queue); + void Shutdown(); + + // Will perform an ownership transfer if the queue is different than the + // current one, and take a reference to the queue. + void SetQueue(ID3D12CommandQueue* new_queue); + + UINT64 GetCurrentSubmission() const { return submission_current_; } + // May be lower than a value awaited by AwaitSubmissionCompletion if it + // returned false. + UINT64 GetCompletedSubmission() const { + // If shut down already or haven't fully initialized yet, don't care, for + // simplicity of external code, as any downloads are unlikely in this case, + // but destruction can be simplified. + return fence_ ? fence_->GetCompletedValue() : (GetCurrentSubmission() - 1); + } + + // Returns whether the expected GPU signal has actually been reached (rather + // than some fallback condition) for cases when stronger completeness + // guarantees as needed (when downloading, as opposed to just destroying). + // If false is returned, it's also not guaranteed that GetCompletedSubmission + // will return a value >= submission_index. + bool AwaitSubmissionCompletion(UINT64 submission_index); + bool AwaitAllSubmissionsCompletion() { + return AwaitSubmissionCompletion(GetCurrentSubmission() - 1); + } + + // Call after a successful ExecuteCommandList. Unconditionally increments the + // current submission index, and tries to enqueue the fence signal. Returns + // true if enqueued successfully, but even if not, waiting for submissions + // without a successfully enqueued signal is handled in the tracker in a way + // that it won't be infinite, so there's no need for clients to revert updates + // to submission indices associated with GPU usage of objects. + bool NextSubmission(); + // If NextSubmission has failed, but it's important that the signal is + // enqueued, can be used to retry enqueueing the signal. + bool TrySignalEnqueueing(); + + private: + UINT64 submission_current_ = 1; + UINT64 submission_signal_queued_ = 0; + HANDLE fence_completion_event_ = nullptr; + Microsoft::WRL::ComPtr fence_; + Microsoft::WRL::ComPtr queue_; +}; + +} // namespace d3d12 +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_D3D12_D3D12_SUBMISSION_TRACKER_H_ diff --git a/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.cc b/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.cc index 0d6cf8b72..b50edfd6e 100644 --- a/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.cc +++ b/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -38,7 +38,7 @@ uint8_t* D3D12UploadBufferPool::Request( return nullptr; } if (buffer_out) { - *buffer_out = page->buffer_; + *buffer_out = page->buffer_.Get(); } if (offset_out) { *offset_out = offset; @@ -61,7 +61,7 @@ uint8_t* D3D12UploadBufferPool::RequestPartial( return nullptr; } if (buffer_out) { - *buffer_out = page->buffer_; + *buffer_out = page->buffer_.Get(); } if (offset_out) { *offset_out = offset; @@ -80,7 +80,7 @@ D3D12UploadBufferPool::CreatePageImplementation() { D3D12_RESOURCE_DESC buffer_desc; util::FillBufferResourceDesc(buffer_desc, page_size_, D3D12_RESOURCE_FLAG_NONE); - ID3D12Resource* buffer; + Microsoft::WRL::ComPtr buffer; if (FAILED(provider_.GetDevice()->CreateCommittedResource( &util::kHeapPropertiesUpload, provider_.GetHeapFlagCreateNotZeroed(), &buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, @@ -97,24 +97,16 @@ D3D12UploadBufferPool::CreatePageImplementation() { buffer->Release(); return nullptr; } - D3D12Page* page = new D3D12Page(buffer, mapping); - // Owned by the page now. - buffer->Release(); - return page; + // Unmapping will be done implicitly when the resource is destroyed. + return new D3D12Page(buffer.Get(), mapping); } D3D12UploadBufferPool::D3D12Page::D3D12Page(ID3D12Resource* buffer, void* mapping) : buffer_(buffer), mapping_(mapping) { - buffer_->AddRef(); gpu_address_ = buffer_->GetGPUVirtualAddress(); } -D3D12UploadBufferPool::D3D12Page::~D3D12Page() { - // Unmapping is done implicitly when the buffer is destroyed. - buffer_->Release(); -} - } // namespace d3d12 } // namespace ui } // namespace xe diff --git a/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h b/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h index 2a8d2ac0a..c35443c5e 100644 --- a/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h +++ b/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -38,8 +38,7 @@ class D3D12UploadBufferPool : public GraphicsUploadBufferPool { // Creates a reference to the buffer. It must not be unmapped until this // D3D12Page is deleted. D3D12Page(ID3D12Resource* buffer, void* mapping); - ~D3D12Page() override; - ID3D12Resource* buffer_; + Microsoft::WRL::ComPtr buffer_; void* mapping_; D3D12_GPU_VIRTUAL_ADDRESS gpu_address_; }; diff --git a/src/xenia/ui/file_picker.h b/src/xenia/ui/file_picker.h index 6a2259007..c2e6e1174 100644 --- a/src/xenia/ui/file_picker.h +++ b/src/xenia/ui/file_picker.h @@ -16,6 +16,8 @@ #include #include +#include "xenia/ui/window.h" + namespace xe { namespace ui { @@ -68,7 +70,7 @@ class FilePicker { selected_files_ = std::move(selected_files); } - virtual bool Show(void* parent_window_handle = nullptr) = 0; + virtual bool Show(Window* parent_window = nullptr) = 0; private: Mode mode_; diff --git a/src/xenia/ui/file_picker_gtk.cc b/src/xenia/ui/file_picker_gtk.cc index 456582906..0b6ed5044 100644 --- a/src/xenia/ui/file_picker_gtk.cc +++ b/src/xenia/ui/file_picker_gtk.cc @@ -19,6 +19,7 @@ #include "xenia/base/filesystem.h" #include "xenia/base/platform_linux.h" #include "xenia/base/string.h" +#include "xenia/ui/window_gtk.h" namespace xe { namespace ui { @@ -28,7 +29,7 @@ class GtkFilePicker : public FilePicker { GtkFilePicker(); ~GtkFilePicker() override; - bool Show(void* parent_window_handle) override; + bool Show(Window* parent_window) override; private: }; @@ -41,7 +42,7 @@ GtkFilePicker::GtkFilePicker() = default; GtkFilePicker::~GtkFilePicker() = default; -bool GtkFilePicker::Show(void* parent_window_handle) { +bool GtkFilePicker::Show(Window* parent_window) { // TODO(benvanik): FileSaveDialog. assert_true(mode() == Mode::kOpen); // TODO(benvanik): folder dialogs. @@ -50,7 +51,10 @@ bool GtkFilePicker::Show(void* parent_window_handle) { gint res; dialog = gtk_file_chooser_dialog_new( - "Open File", (GtkWindow*)parent_window_handle, + "Open File", + parent_window + ? GTK_WINDOW(static_cast(parent_window)->window()) + : nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", GTK_RESPONSE_CANCEL, "_Open", GTK_RESPONSE_ACCEPT, NULL); diff --git a/src/xenia/ui/file_picker_win.cc b/src/xenia/ui/file_picker_win.cc index d2d7bf33d..88ce056bc 100644 --- a/src/xenia/ui/file_picker_win.cc +++ b/src/xenia/ui/file_picker_win.cc @@ -11,6 +11,7 @@ #include "xenia/base/platform_win.h" #include "xenia/base/string.h" #include "xenia/ui/file_picker.h" +#include "xenia/ui/window_win.h" // Microsoft headers after platform_win.h. #include @@ -23,7 +24,7 @@ class Win32FilePicker : public FilePicker { Win32FilePicker(); ~Win32FilePicker() override; - bool Show(void* parent_window_handle) override; + bool Show(Window* parent_window) override; private: }; @@ -109,7 +110,7 @@ Win32FilePicker::Win32FilePicker() = default; Win32FilePicker::~Win32FilePicker() = default; -bool Win32FilePicker::Show(void* parent_window_handle) { +bool Win32FilePicker::Show(Window* parent_window) { // TODO(benvanik): FileSaveDialog. assert_true(mode() == Mode::kOpen); // TODO(benvanik): folder dialogs. @@ -179,7 +180,9 @@ bool Win32FilePicker::Show(void* parent_window_handle) { } // Show the dialog modally. - hr = file_dialog->Show(static_cast(parent_window_handle)); + hr = file_dialog->Show( + parent_window ? static_cast(parent_window)->hwnd() + : nullptr); file_dialog->Unadvise(cookie); if (!SUCCEEDED(hr)) { return false; diff --git a/src/xenia/ui/graphics_context.cc b/src/xenia/ui/graphics_context.cc deleted file mode 100644 index 7f5ab07b6..000000000 --- a/src/xenia/ui/graphics_context.cc +++ /dev/null @@ -1,48 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/graphics_context.h" - -#include - -#include "xenia/base/cvar.h" -#include "xenia/ui/graphics_provider.h" - -DEFINE_bool(random_clear_color, false, "Randomize window clear color.", "UI"); - -namespace xe { -namespace ui { - -GraphicsContext::GraphicsContext(GraphicsProvider* provider, - Window* target_window) - : provider_(provider), target_window_(target_window) {} - -GraphicsContext::~GraphicsContext() = default; - -bool GraphicsContext::is_current() { return true; } - -bool GraphicsContext::MakeCurrent() { return true; } - -void GraphicsContext::ClearCurrent() {} - -void GraphicsContext::GetClearColor(float* rgba) { - if (cvars::random_clear_color) { - rgba[0] = rand() / float(RAND_MAX); // NOLINT(runtime/threadsafe_fn) - rgba[1] = 1.0f; - rgba[2] = 0.0f; - } else { - rgba[0] = 0.0f; - rgba[1] = 0.0f; - rgba[2] = 0.0f; - } - rgba[3] = 1.0f; -} - -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/graphics_context.h b/src/xenia/ui/graphics_context.h deleted file mode 100644 index 0ed5bd881..000000000 --- a/src/xenia/ui/graphics_context.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_GRAPHICS_CONTEXT_H_ -#define XENIA_UI_GRAPHICS_CONTEXT_H_ - -#include -#include - -namespace xe { -namespace ui { - -class GraphicsProvider; -class ImmediateDrawer; -class Window; - -class RawImage { - public: - RawImage() = default; - ~RawImage() = default; - - size_t width = 0; - size_t height = 0; - size_t stride = 0; - std::vector data; -}; - -class GraphicsContext { - public: - virtual ~GraphicsContext(); - - GraphicsProvider* provider() const { return provider_; } - Window* target_window() const { return target_window_; } - bool is_offscreen() { return immediate_drawer() == nullptr; } - - virtual ImmediateDrawer* immediate_drawer() = 0; - - virtual bool is_current(); - virtual bool MakeCurrent(); - virtual void ClearCurrent(); - - // Returns true if the OS took away our context because we caused a TDR or - // some other outstanding error. When this happens, this context, as well as - // any other shared contexts are junk. - // This context must be made current in order for this call to work properly. - virtual bool WasLost() = 0; - - // Returns true if able to draw now (the target surface is available). - virtual bool BeginSwap() = 0; - virtual void EndSwap() = 0; - - virtual std::unique_ptr Capture() = 0; - - protected: - explicit GraphicsContext(GraphicsProvider* provider, Window* target_window); - - static void GetClearColor(float* rgba); - - GraphicsProvider* provider_ = nullptr; - Window* target_window_ = nullptr; -}; - -struct GraphicsContextLock { - explicit GraphicsContextLock(GraphicsContext* context) : context_(context) { - was_current_ = context_->is_current(); - if (!was_current_) { - context_->MakeCurrent(); - } - } - ~GraphicsContextLock() { - if (!was_current_) { - context_->ClearCurrent(); - } - } - - private: - bool was_current_ = false; - GraphicsContext* context_ = nullptr; -}; - -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_GRAPHICS_CONTEXT_H_ diff --git a/src/xenia/ui/graphics_provider.h b/src/xenia/ui/graphics_provider.h index 4a1645d80..08c78cd1f 100644 --- a/src/xenia/ui/graphics_provider.h +++ b/src/xenia/ui/graphics_provider.h @@ -12,10 +12,12 @@ #include +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" + namespace xe { namespace ui { -class GraphicsContext; class Window; // Factory for graphics contexts. @@ -36,13 +38,13 @@ class GraphicsProvider { virtual ~GraphicsProvider() = default; - // Creates a new host-side graphics context and swapchain, possibly presenting - // to a window and using the immediate drawer. - virtual std::unique_ptr CreateHostContext( - Window* target_window) = 0; + // It's safe to reinitialize the presenter in the host GPU loss callback if it + // was called from the UI thread as specified in the arguments. + virtual std::unique_ptr CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback = + Presenter::FatalErrorHostGpuLossCallback) = 0; - // Creates a new offscreen emulation graphics context. - virtual std::unique_ptr CreateEmulationContext() = 0; + virtual std::unique_ptr CreateImmediateDrawer() = 0; protected: GraphicsProvider() = default; diff --git a/src/xenia/ui/graphics_upload_buffer_pool.cc b/src/xenia/ui/graphics_upload_buffer_pool.cc index 5eb04fba3..d68085b8d 100644 --- a/src/xenia/ui/graphics_upload_buffer_pool.cc +++ b/src/xenia/ui/graphics_upload_buffer_pool.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -38,6 +38,25 @@ void GraphicsUploadBufferPool::Reclaim(uint64_t completed_submission_index) { } } +void GraphicsUploadBufferPool::ChangeSubmissionTimeline() { + // Reclaim all submitted pages. + if (writable_last_) { + writable_last_->next_ = submitted_first_; + } else { + writable_first_ = submitted_first_; + } + writable_last_ = submitted_last_; + submitted_first_ = nullptr; + submitted_last_ = nullptr; + + // Mark all pages as never used yet in the new timeline. + Page* page = writable_first_; + while (page) { + page->last_submission_index_ = 0; + page = page->next_; + } +} + void GraphicsUploadBufferPool::ClearCache() { // Called from the destructor - must not call virtual functions here. current_page_flushed_ = 0; diff --git a/src/xenia/ui/graphics_upload_buffer_pool.h b/src/xenia/ui/graphics_upload_buffer_pool.h index 7f5a714d3..00f628af6 100644 --- a/src/xenia/ui/graphics_upload_buffer_pool.h +++ b/src/xenia/ui/graphics_upload_buffer_pool.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,9 +13,13 @@ #include #include +#include "xenia/base/literals.h" + namespace xe { namespace ui { +using namespace xe::literals; + // Submission index is the fence value or a value derived from it (if reclaiming // less often than once per fence value, for instance). @@ -23,11 +27,12 @@ class GraphicsUploadBufferPool { public: // Taken from the Direct3D 12 MiniEngine sample (LinearAllocator // kCpuAllocatorPageSize). Large enough for most cases. - static constexpr size_t kDefaultPageSize = 2 * 1024 * 1024; + static constexpr size_t kDefaultPageSize = 2_MiB; virtual ~GraphicsUploadBufferPool(); void Reclaim(uint64_t completed_submission_index); + void ChangeSubmissionTimeline(); void ClearCache(); // Should be called before submitting anything using this pool, unless the diff --git a/src/xenia/ui/graphics_util.cc b/src/xenia/ui/graphics_util.cc new file mode 100644 index 000000000..b69bc44b3 --- /dev/null +++ b/src/xenia/ui/graphics_util.cc @@ -0,0 +1,63 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/graphics_util.h" + +#include + +namespace xe { +namespace ui { + +int32_t FloatToD3D11Fixed16p8(float f32) { + // https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#3.2.4.1%20FLOAT%20-%3E%20Fixed%20Point%20Integer + // Early exit tests. + // n == NaN || n.unbiasedExponent < -f-1 -> 0 . 0 + if (!(std::abs(f32) >= 1.0f / 512.0f)) { + return 0; + } + // n >= (2^(i-1)-2^-f) -> 2^(i-1)-1 . 2^f-1 + if (f32 >= 32768.0f - 1.0f / 256.0f) { + return (1 << 23) - 1; + } + // n <= -2^(i-1) -> -2^(i-1) . 0 + if (f32 <= -32768.0f) { + return -32768 * 256; + } + uint32_t f32_bits = *reinterpret_cast(&f32); + // Copy float32 mantissa bits [22:0] into corresponding bits [22:0] of a + // result buffer that has at least 24 bits total storage (before reaching + // rounding step further below). This includes one bit for the hidden 1. + // Set bit [23] (float32 hidden bit). + // Clear bits [31:24]. + union { + int32_t s; + uint32_t u; + } result; + result.u = (f32_bits & ((1 << 23) - 1)) | (1 << 23); + // If the sign bit is set in the float32 number (negative), then take the 2's + // component of the entire set of bits. + if ((f32_bits >> 31) != 0) { + result.s = -result.s; + } + // Final calculation: extraBits = (mantissa - f) - n.unbiasedExponent + // (guaranteed to be >= 0). + int32_t exponent = int32_t((f32_bits >> 23) & 255) - 127; + uint32_t extra_bits = uint32_t(15 - exponent); + if (extra_bits) { + // Round the 32-bit value to a decimal that is extraBits to the left of + // the LSB end, using nearest-even. + result.u += (1 << (extra_bits - 1)) - 1 + ((result.u >> extra_bits) & 1); + // Shift right by extraBits (sign extending). + result.s >>= extra_bits; + } + return result.s; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/graphics_util.h b/src/xenia/ui/graphics_util.h new file mode 100644 index 000000000..b3aa19a33 --- /dev/null +++ b/src/xenia/ui/graphics_util.h @@ -0,0 +1,30 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_GRAPHICS_UTIL_H_ +#define XENIA_UI_GRAPHICS_UTIL_H_ + +#include + +namespace xe { +namespace ui { + +// For estimating coverage extents from vertices. This may give results that are +// different than what the GPU will actually draw (this is the reference +// conversion with 1/2 ULP accuracy, but Direct3D 11 permits 0.6 ULP tolerance +// in floating point to fixed point conversion), but is enough to tie-break +// vertices at pixel centers (due to the half-pixel offset applied to integer +// coordinates incorrectly, for instance) with some error tolerance near 0.5, +// for use with the top-left rasterization rule later. +int32_t FloatToD3D11Fixed16p8(float f32); + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_GRAPHICS_UTIL_H_ diff --git a/src/xenia/ui/imgui_dialog.cc b/src/xenia/ui/imgui_dialog.cc index 2e2370bd9..4e940e798 100644 --- a/src/xenia/ui/imgui_dialog.cc +++ b/src/xenia/ui/imgui_dialog.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -11,20 +11,18 @@ #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" -#include "xenia/ui/window.h" +#include "xenia/ui/imgui_drawer.h" namespace xe { namespace ui { -ImGuiDialog::ImGuiDialog(Window* window) : window_(window) { - window_->AttachListener(this); - had_imgui_active_ = window_->is_imgui_input_enabled(); - window_->set_imgui_input_enabled(true); +ImGuiDialog::ImGuiDialog(ImGuiDrawer* imgui_drawer) + : imgui_drawer_(imgui_drawer) { + imgui_drawer_->AddDialog(this); } ImGuiDialog::~ImGuiDialog() { - window_->set_imgui_input_enabled(had_imgui_active_); - window_->DetachListener(this); + imgui_drawer_->RemoveDialog(this); for (auto fence : waiting_fences_) { fence->Signal(); } @@ -36,12 +34,9 @@ void ImGuiDialog::Then(xe::threading::Fence* fence) { void ImGuiDialog::Close() { has_close_pending_ = true; } -ImGuiIO& ImGuiDialog::GetIO() { return window_->imgui_drawer()->GetIO(); } - -void ImGuiDialog::OnPaint(UIEvent* e) { - // Keep imgui rendering every frame. - window_->Invalidate(); +ImGuiIO& ImGuiDialog::GetIO() { return imgui_drawer()->GetIO(); } +void ImGuiDialog::Draw() { // Draw UI. OnDraw(GetIO()); @@ -52,10 +47,13 @@ void ImGuiDialog::OnPaint(UIEvent* e) { } } -class MessageBoxDialog : public ImGuiDialog { +class MessageBoxDialog final : public ImGuiDialog { public: - MessageBoxDialog(Window* window, std::string title, std::string body) - : ImGuiDialog(window), title_(std::move(title)), body_(std::move(body)) {} + MessageBoxDialog(ImGuiDrawer* imgui_drawer, std::string title, + std::string body) + : ImGuiDialog(imgui_drawer), + title_(std::move(title)), + body_(std::move(body)) {} void OnDraw(ImGuiIO& io) override { if (!has_opened_) { @@ -84,9 +82,9 @@ class MessageBoxDialog : public ImGuiDialog { std::string body_; }; -ImGuiDialog* ImGuiDialog::ShowMessageBox(Window* window, std::string title, - std::string body) { - return new MessageBoxDialog(window, std::move(title), std::move(body)); +ImGuiDialog* ImGuiDialog::ShowMessageBox(ImGuiDrawer* imgui_drawer, + std::string title, std::string body) { + return new MessageBoxDialog(imgui_drawer, std::move(title), std::move(body)); } } // namespace ui diff --git a/src/xenia/ui/imgui_dialog.h b/src/xenia/ui/imgui_dialog.h index 3c9632c07..454659bea 100644 --- a/src/xenia/ui/imgui_dialog.h +++ b/src/xenia/ui/imgui_dialog.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -19,23 +19,25 @@ namespace xe { namespace ui { -class ImGuiDialog : private WindowListener { +class ImGuiDialog { public: ~ImGuiDialog(); // Shows a simple message box containing a text message. // Callers can want for the dialog to close with Wait(). // Dialogs retain themselves and will delete themselves when closed. - static ImGuiDialog* ShowMessageBox(Window* window, std::string title, - std::string body); + static ImGuiDialog* ShowMessageBox(ImGuiDrawer* imgui_drawer, + std::string title, std::string body); // A fence to signal when the dialog is closed. void Then(xe::threading::Fence* fence); - protected: - ImGuiDialog(Window* window); + void Draw(); - Window* window() const { return window_; } + protected: + ImGuiDialog(ImGuiDrawer* imgui_drawer); + + ImGuiDrawer* imgui_drawer() const { return imgui_drawer_; } ImGuiIO& GetIO(); // Closes the dialog and returns to any waiters. @@ -46,10 +48,7 @@ class ImGuiDialog : private WindowListener { virtual void OnDraw(ImGuiIO& io) {} private: - void OnPaint(UIEvent* e) override; - - Window* window_ = nullptr; - bool had_imgui_active_ = false; + ImGuiDrawer* imgui_drawer_ = nullptr; bool has_close_pending_ = false; std::vector waiting_fences_; }; diff --git a/src/xenia/ui/imgui_drawer.cc b/src/xenia/ui/imgui_drawer.cc index 276cea114..c3ab41906 100644 --- a/src/xenia/ui/imgui_drawer.cc +++ b/src/xenia/ui/imgui_drawer.cc @@ -2,17 +2,23 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/ui/imgui_drawer.h" +#include +#include + #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" +#include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/window.h" namespace xe { @@ -26,18 +32,75 @@ const char kProggyTinyCompressedDataBase85[10950 + 1] = static_assert(sizeof(ImmediateVertex) == sizeof(ImDrawVert), "Vertex types must match"); -ImGuiDrawer::ImGuiDrawer(xe::ui::Window* window) - : window_(window), graphics_context_(window->context()) { +ImGuiDrawer::ImGuiDrawer(xe::ui::Window* window, size_t z_order) + : window_(window), z_order_(z_order) { Initialize(); } ImGuiDrawer::~ImGuiDrawer() { + SetPresenter(nullptr); + if (!dialogs_.empty()) { + window_->RemoveInputListener(this); + if (internal_state_) { + ImGui::SetCurrentContext(internal_state_); + if (ImGui::IsAnyMouseDown()) { + window_->ReleaseMouse(); + } + } + } if (internal_state_) { ImGui::DestroyContext(internal_state_); internal_state_ = nullptr; } } +void ImGuiDrawer::AddDialog(ImGuiDialog* dialog) { + assert_not_null(dialog); + // Check if already added. + if (std::find(dialogs_.cbegin(), dialogs_.cend(), dialog) != + dialogs_.cend()) { + return; + } + if (dialog_loop_next_index_ == SIZE_MAX && dialogs_.empty()) { + // First dialog added. dialog_loop_next_index_ == SIZE_MAX is also checked + // because in a situation of removing the only dialog, then adding a dialog, + // from within a dialog's Draw function, the removal would not cause the + // listener and the drawer to be removed (it's deferred in this case). + window_->AddInputListener(this, z_order_); + if (presenter_) { + presenter_->AddUIDrawerFromUIThread(this, z_order_); + } + } + dialogs_.push_back(dialog); +} + +void ImGuiDrawer::RemoveDialog(ImGuiDialog* dialog) { + assert_not_null(dialog); + auto it = std::find(dialogs_.cbegin(), dialogs_.cend(), dialog); + if (it == dialogs_.cend()) { + return; + } + if (dialog_loop_next_index_ != SIZE_MAX) { + // Actualize the next dialog index after the erasure from the vector. + size_t existing_index = size_t(std::distance(dialogs_.cbegin(), it)); + if (dialog_loop_next_index_ > existing_index) { + --dialog_loop_next_index_; + } + } + dialogs_.erase(it); + if (dialog_loop_next_index_ == SIZE_MAX && dialogs_.empty()) { + if (presenter_) { + presenter_->RemoveUIDrawerFromUIThread(this); + } + window_->RemoveInputListener(this); + // Clear all input since no input will be received anymore, and when the + // drawer becomes active again, it'd have an outdated input state otherwise + // which will be persistent until new events actualize individual input + // properties. + ClearInput(); + } +} + void ImGuiDrawer::Initialize() { // Setup ImGui internal state. // This will give us state we can swap to the ImGui globals when in use. @@ -51,9 +114,31 @@ void ImGuiDrawer::Initialize() { // Windows. io.IniFilename = nullptr; - SetupFont(); - - io.DeltaTime = 1.0f / 60.0f; + // Setup the font glyphs. + ImFontConfig font_config; + font_config.OversampleH = font_config.OversampleV = 1; + font_config.PixelSnapH = true; + static const ImWchar font_glyph_ranges[] = { + 0x0020, + 0x00FF, // Basic Latin + Latin Supplement + 0, + }; + io.Fonts->AddFontFromMemoryCompressedBase85TTF( + kProggyTinyCompressedDataBase85, 10.0f, &font_config, font_glyph_ranges); + // TODO(benvanik): jp font on other platforms? + // https://github.com/Koruri/kibitaki looks really good, but is 1.5MiB. + const char* jp_font_path = "C:\\Windows\\Fonts\\msgothic.ttc"; + if (std::filesystem::exists(jp_font_path)) { + ImFontConfig jp_font_config; + jp_font_config.MergeMode = true; + jp_font_config.OversampleH = jp_font_config.OversampleV = 1; + jp_font_config.PixelSnapH = true; + jp_font_config.FontNo = 0; + io.Fonts->AddFontFromFileTTF(jp_font_path, 12.0f, &jp_font_config, + io.Fonts->GetGlyphRangesJapanese()); + } else { + XELOGW("Unable to load Japanese font; JP characters will be boxes"); + } auto& style = ImGui::GetStyle(); style.ScrollbarRounding = 0; @@ -125,60 +210,121 @@ void ImGuiDrawer::Initialize() { io.KeyMap[ImGuiKey_X] = int(ui::VirtualKey::kX); io.KeyMap[ImGuiKey_Y] = int(ui::VirtualKey::kY); io.KeyMap[ImGuiKey_Z] = int(ui::VirtualKey::kZ); + + frame_time_tick_frequency_ = double(Clock::QueryHostTickFrequency()); + last_frame_time_ticks_ = Clock::QueryHostTickCount(); } -void ImGuiDrawer::SetupFont() { - auto& io = GetIO(); - - ImFontConfig font_config; - font_config.OversampleH = font_config.OversampleV = 1; - font_config.PixelSnapH = true; - static const ImWchar font_glyph_ranges[] = { - 0x0020, - 0x00FF, // Basic Latin + Latin Supplement - 0, - }; - io.Fonts->AddFontFromMemoryCompressedBase85TTF( - kProggyTinyCompressedDataBase85, 10.0f, &font_config, font_glyph_ranges); - - // TODO(benvanik): jp font on other platforms? - // https://github.com/Koruri/kibitaki looks really good, but is 1.5MiB. - const char* jp_font_path = "C:\\Windows\\Fonts\\msgothic.ttc"; - if (std::filesystem::exists(jp_font_path)) { - ImFontConfig jp_font_config; - jp_font_config.MergeMode = true; - jp_font_config.OversampleH = jp_font_config.OversampleV = 1; - jp_font_config.PixelSnapH = true; - jp_font_config.FontNo = 0; - io.Fonts->AddFontFromFileTTF(jp_font_path, 12.0f, &jp_font_config, - io.Fonts->GetGlyphRangesJapanese()); - } else { - XELOGW("Unable to load japanese font; jp characters will be boxes"); +void ImGuiDrawer::SetupFontTexture() { + if (font_texture_ || !immediate_drawer_) { + return; } - + ImGuiIO& io = GetIO(); unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - font_texture_ = graphics_context_->immediate_drawer()->CreateTexture( + font_texture_ = immediate_drawer_->CreateTexture( width, height, ImmediateTextureFilter::kLinear, true, reinterpret_cast(pixels)); - io.Fonts->TexID = reinterpret_cast(font_texture_.get()); } -void ImGuiDrawer::RenderDrawLists(ImDrawData* data) { - auto drawer = graphics_context_->immediate_drawer(); +void ImGuiDrawer::SetPresenter(Presenter* new_presenter) { + if (presenter_) { + if (presenter_ == new_presenter) { + return; + } + if (!dialogs_.empty()) { + presenter_->RemoveUIDrawerFromUIThread(this); + } + ImGuiIO& io = GetIO(); + } + presenter_ = new_presenter; + if (presenter_) { + if (!dialogs_.empty()) { + presenter_->AddUIDrawerFromUIThread(this, z_order_); + } + } +} + +void ImGuiDrawer::SetImmediateDrawer(ImmediateDrawer* new_immediate_drawer) { + if (immediate_drawer_ == new_immediate_drawer) { + return; + } + if (immediate_drawer_) { + GetIO().Fonts->TexID = static_cast(nullptr); + font_texture_.reset(); + } + immediate_drawer_ = new_immediate_drawer; + if (immediate_drawer_) { + SetupFontTexture(); + } +} + +void ImGuiDrawer::Draw(UIDrawContext& ui_draw_context) { + // Drawing of anything is initiated by the presenter. + assert_not_null(presenter_); + if (!immediate_drawer_) { + // A presenter has been attached, but an immediate drawer hasn't been + // attached yet. + return; + } + + if (dialogs_.empty()) { + return; + } + + ImGui::SetCurrentContext(internal_state_); - // Handle cases of screen coordinates != from framebuffer coordinates (e.g. - // retina displays). ImGuiIO& io = ImGui::GetIO(); - float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y; - data->ScaleClipRects(io.DisplayFramebufferScale); - const float width = io.DisplaySize.x; - const float height = io.DisplaySize.y; - drawer->Begin(static_cast(width), static_cast(height)); + uint64_t current_frame_time_ticks = Clock::QueryHostTickCount(); + io.DeltaTime = + float(double(current_frame_time_ticks - last_frame_time_ticks_) / + frame_time_tick_frequency_); + if (!(io.DeltaTime > 0.0f) || + current_frame_time_ticks < last_frame_time_ticks_) { + // For safety as Dear ImGui doesn't allow non-positive DeltaTime. Using the + // same default value as in the official samples. + io.DeltaTime = 1.0f / 60.0f; + } + last_frame_time_ticks_ = current_frame_time_ticks; + + float physical_to_logical = + float(window_->GetMediumDpi()) / float(window_->GetDpi()); + io.DisplaySize.x = window_->GetActualPhysicalWidth() * physical_to_logical; + io.DisplaySize.y = window_->GetActualPhysicalHeight() * physical_to_logical; + + ImGui::NewFrame(); + + assert_true(dialog_loop_next_index_ == SIZE_MAX); + dialog_loop_next_index_ = 0; + while (dialog_loop_next_index_ < dialogs_.size()) { + dialogs_[dialog_loop_next_index_++]->Draw(); + } + dialog_loop_next_index_ = SIZE_MAX; + + ImGui::Render(); + ImDrawData* draw_data = ImGui::GetDrawData(); + if (draw_data) { + RenderDrawLists(draw_data, ui_draw_context); + } + + if (dialogs_.empty()) { + // All dialogs have removed themselves during the draw, detach. + presenter_->RemoveUIDrawerFromUIThread(this); + window_->RemoveInputListener(this); + } else { + // Repaint (and handle input) continuously if still active. + presenter_->RequestUIPaintFromUIThread(); + } +} + +void ImGuiDrawer::RenderDrawLists(ImDrawData* data, + UIDrawContext& ui_draw_context) { + ImGuiIO& io = ImGui::GetIO(); + + immediate_drawer_->Begin(ui_draw_context, io.DisplaySize.x, io.DisplaySize.y); for (int i = 0; i < data->CmdListsCount; ++i) { const auto cmd_list = data->CmdLists[i]; @@ -189,7 +335,7 @@ void ImGuiDrawer::RenderDrawLists(ImDrawData* data) { batch.vertex_count = cmd_list->VtxBuffer.size(); batch.indices = cmd_list->IdxBuffer.Data; batch.index_count = cmd_list->IdxBuffer.size(); - drawer->BeginDrawBatch(batch); + immediate_drawer_->BeginDrawBatch(batch); int index_offset = 0; for (int j = 0; j < cmd_list->CmdBuffer.size(); ++j) { @@ -201,19 +347,19 @@ void ImGuiDrawer::RenderDrawLists(ImDrawData* data) { draw.index_offset = index_offset; draw.texture = reinterpret_cast(cmd.TextureId); draw.scissor = true; - draw.scissor_rect[0] = static_cast(cmd.ClipRect.x); - draw.scissor_rect[1] = static_cast(height - cmd.ClipRect.w); - draw.scissor_rect[2] = static_cast(cmd.ClipRect.z - cmd.ClipRect.x); - draw.scissor_rect[3] = static_cast(cmd.ClipRect.w - cmd.ClipRect.y); - drawer->Draw(draw); + draw.scissor_left = cmd.ClipRect.x; + draw.scissor_top = cmd.ClipRect.y; + draw.scissor_right = cmd.ClipRect.z; + draw.scissor_bottom = cmd.ClipRect.w; + immediate_drawer_->Draw(draw); index_offset += cmd.ElemCount; } - drawer->EndDrawBatch(); + immediate_drawer_->EndDrawBatch(); } - drawer->End(); + immediate_drawer_->End(); } ImGuiIO& ImGuiDrawer::GetIO() { @@ -221,33 +367,25 @@ ImGuiIO& ImGuiDrawer::GetIO() { return ImGui::GetIO(); } -void ImGuiDrawer::RenderDrawLists() { - ImGui::SetCurrentContext(internal_state_); - auto draw_data = ImGui::GetDrawData(); - if (draw_data) { - RenderDrawLists(draw_data); - } -} +void ImGuiDrawer::OnKeyDown(KeyEvent& e) { OnKey(e, true); } -void ImGuiDrawer::OnKeyDown(KeyEvent* e) { OnKey(e, true); } +void ImGuiDrawer::OnKeyUp(KeyEvent& e) { OnKey(e, false); } -void ImGuiDrawer::OnKeyUp(KeyEvent* e) { OnKey(e, false); } - -void ImGuiDrawer::OnKeyChar(KeyEvent* e) { +void ImGuiDrawer::OnKeyChar(KeyEvent& e) { auto& io = GetIO(); // TODO(Triang3l): Accept the Unicode character. - unsigned int character = static_cast(e->virtual_key()); + unsigned int character = static_cast(e.virtual_key()); if (character > 0 && character < 0x10000) { io.AddInputCharacter(character); - e->set_handled(true); + e.set_handled(true); } } -void ImGuiDrawer::OnMouseDown(MouseEvent* e) { +void ImGuiDrawer::OnMouseDown(MouseEvent& e) { + UpdateMousePosition(e); auto& io = GetIO(); - io.MousePos = ImVec2(float(e->x()), float(e->y())); int button = -1; - switch (e->button()) { + switch (e.button()) { case xe::ui::MouseEvent::Button::kLeft: { button = 0; break; @@ -261,25 +399,23 @@ void ImGuiDrawer::OnMouseDown(MouseEvent* e) { break; } } - if (button >= 0 && button < std::size(io.MouseDown)) { - if (!ImGui::IsAnyMouseDown()) { - window_->CaptureMouse(); + if (!io.MouseDown[button]) { + if (!ImGui::IsAnyMouseDown()) { + window_->CaptureMouse(); + } + io.MouseDown[button] = true; } - io.MouseDown[button] = true; } } -void ImGuiDrawer::OnMouseMove(MouseEvent* e) { - auto& io = GetIO(); - io.MousePos = ImVec2(float(e->x()), float(e->y())); -} +void ImGuiDrawer::OnMouseMove(MouseEvent& e) { UpdateMousePosition(e); } -void ImGuiDrawer::OnMouseUp(MouseEvent* e) { +void ImGuiDrawer::OnMouseUp(MouseEvent& e) { + UpdateMousePosition(e); auto& io = GetIO(); - io.MousePos = ImVec2(float(e->x()), float(e->y())); int button = -1; - switch (e->button()) { + switch (e.button()) { case xe::ui::MouseEvent::Button::kLeft: { button = 0; break; @@ -293,24 +429,42 @@ void ImGuiDrawer::OnMouseUp(MouseEvent* e) { break; } } - if (button >= 0 && button < std::size(io.MouseDown)) { - io.MouseDown[button] = false; - if (!ImGui::IsAnyMouseDown()) { - window_->ReleaseMouse(); + if (io.MouseDown[button]) { + io.MouseDown[button] = false; + if (!ImGui::IsAnyMouseDown()) { + window_->ReleaseMouse(); + } } } } -void ImGuiDrawer::OnMouseWheel(MouseEvent* e) { +void ImGuiDrawer::OnMouseWheel(MouseEvent& e) { + UpdateMousePosition(e); auto& io = GetIO(); - io.MousePos = ImVec2(float(e->x()), float(e->y())); - io.MouseWheel += float(e->dy() / 120.0f); + io.MouseWheel += float(e.scroll_y()) / float(MouseEvent::kScrollPerDetent); } -void ImGuiDrawer::OnKey(KeyEvent* e, bool is_down) { +void ImGuiDrawer::ClearInput() { auto& io = GetIO(); - VirtualKey virtual_key = e->virtual_key(); + if (ImGui::IsAnyMouseDown()) { + window_->ReleaseMouse(); + } + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + std::memset(io.MouseDown, 0, sizeof(io.MouseDown)); + io.MouseWheel = 0.0f; + io.MouseWheelH = 0.0f; + io.KeyCtrl = false; + io.KeyShift = false; + io.KeyAlt = false; + io.KeySuper = false; + std::memset(io.KeysDown, 0, sizeof(io.KeysDown)); + io.ClearInputCharacters(); +} + +void ImGuiDrawer::OnKey(KeyEvent& e, bool is_down) { + auto& io = GetIO(); + VirtualKey virtual_key = e.virtual_key(); if (size_t(virtual_key) < xe::countof(io.KeysDown)) { io.KeysDown[size_t(virtual_key)] = is_down; } @@ -333,5 +487,13 @@ void ImGuiDrawer::OnKey(KeyEvent* e, bool is_down) { } } +void ImGuiDrawer::UpdateMousePosition(const MouseEvent& e) { + auto& io = GetIO(); + float physical_to_logical = + float(window_->GetMediumDpi()) / float(window_->GetDpi()); + io.MousePos.x = e.x() * physical_to_logical; + io.MousePos.y = e.y() * physical_to_logical; +} + } // namespace ui } // namespace xe diff --git a/src/xenia/ui/imgui_drawer.h b/src/xenia/ui/imgui_drawer.h index 2c370b2aa..fee5c4242 100644 --- a/src/xenia/ui/imgui_drawer.h +++ b/src/xenia/ui/imgui_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,10 +10,14 @@ #ifndef XENIA_UI_IMGUI_DRAWER_H_ #define XENIA_UI_IMGUI_DRAWER_H_ +#include +#include #include #include #include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/window.h" #include "xenia/ui/window_listener.h" struct ImDrawData; @@ -23,43 +27,73 @@ struct ImGuiIO; namespace xe { namespace ui { -class GraphicsContext; +class ImGuiDialog; class Window; -class ImGuiDrawer : public WindowListener { +class ImGuiDrawer : public WindowInputListener, public UIDrawer { public: - ImGuiDrawer(Window* window); + ImGuiDrawer(Window* window, size_t z_order); ~ImGuiDrawer(); - void SetupDefaultInput() {} - ImGuiIO& GetIO(); - void RenderDrawLists(); + + void AddDialog(ImGuiDialog* dialog); + void RemoveDialog(ImGuiDialog* dialog); + + // SetPresenter may be called from the destructor. + void SetPresenter(Presenter* new_presenter); + void SetImmediateDrawer(ImmediateDrawer* new_immediate_drawer); + void SetPresenterAndImmediateDrawer(Presenter* new_presenter, + ImmediateDrawer* new_immediate_drawer) { + SetPresenter(new_presenter); + SetImmediateDrawer(new_immediate_drawer); + } + + void Draw(UIDrawContext& ui_draw_context) override; protected: - void Initialize(); - void SetupFont(); - - void RenderDrawLists(ImDrawData* data); - - void OnKeyDown(KeyEvent* e) override; - void OnKeyUp(KeyEvent* e) override; - void OnKeyChar(KeyEvent* e) override; - void OnMouseDown(MouseEvent* e) override; - void OnMouseMove(MouseEvent* e) override; - void OnMouseUp(MouseEvent* e) override; - void OnMouseWheel(MouseEvent* e) override; - - static ImGuiDrawer* current_drawer_; - - Window* window_ = nullptr; - GraphicsContext* graphics_context_ = nullptr; - - ImGuiContext* internal_state_ = nullptr; - std::unique_ptr font_texture_; + void OnKeyDown(KeyEvent& e) override; + void OnKeyUp(KeyEvent& e) override; + void OnKeyChar(KeyEvent& e) override; + void OnMouseDown(MouseEvent& e) override; + void OnMouseMove(MouseEvent& e) override; + void OnMouseUp(MouseEvent& e) override; + void OnMouseWheel(MouseEvent& e) override; + // For now, no need for OnDpiChanged because redrawing is done continuously. private: - void OnKey(KeyEvent* e, bool is_down); + void Initialize(); + + void SetupFontTexture(); + + void RenderDrawLists(ImDrawData* data, UIDrawContext& ui_draw_context); + + void ClearInput(); + void OnKey(KeyEvent& e, bool is_down); + void UpdateMousePosition(const MouseEvent& e); + + Window* window_; + size_t z_order_; + + ImGuiContext* internal_state_ = nullptr; + + // All currently-attached dialogs that get drawn. + std::vector dialogs_; + // Using an index, not an iterator, because after the erasure, the adjustment + // must be done for the vector element indices that would be in the iterator + // range that would be invalidated. + // SIZE_MAX if not currently in the dialog loop. + size_t dialog_loop_next_index_ = SIZE_MAX; + + Presenter* presenter_ = nullptr; + + ImmediateDrawer* immediate_drawer_ = nullptr; + // Resources specific to an immediate drawer - must be destroyed before + // detaching the presenter. + std::unique_ptr font_texture_; + + double frame_time_tick_frequency_; + uint64_t last_frame_time_ticks_; }; } // namespace ui diff --git a/src/xenia/ui/immediate_drawer.cc b/src/xenia/ui/immediate_drawer.cc new file mode 100644 index 000000000..fb00be77f --- /dev/null +++ b/src/xenia/ui/immediate_drawer.cc @@ -0,0 +1,108 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/immediate_drawer.h" + +#include + +#include "xenia/base/assert.h" +#include "xenia/ui/graphics_util.h" +#include "xenia/ui/presenter.h" + +namespace xe { +namespace ui { + +void ImmediateDrawer::SetPresenter(Presenter* new_presenter) { + if (presenter_ == new_presenter) { + return; + } + // Changing the presenter while drawing would make the state inconsistent. + assert_null(ui_draw_context_); + if (presenter_) { + OnLeavePresenter(); + } + presenter_ = new_presenter; + if (presenter_) { + OnEnterPresenter(); + } +} + +void ImmediateDrawer::Begin(UIDrawContext& ui_draw_context, + float coordinate_space_width, + float coordinate_space_height) { + assert_true(&ui_draw_context.presenter() == presenter_); + ui_draw_context_ = &ui_draw_context; + // In case of non-positive values (or NaNs) - use render target coordinates + // according to the contract of the function, and also for safety because + // there will be division by the coordinate space size in several places. + if (!(coordinate_space_width > 0.0f) || !(coordinate_space_height > 0.0f)) { + coordinate_space_width = float(ui_draw_context.render_target_width()); + coordinate_space_height = float(ui_draw_context.render_target_height()); + } + coordinate_space_width_ = coordinate_space_width; + coordinate_space_height_ = coordinate_space_height; +} + +void ImmediateDrawer::End() { ui_draw_context_ = nullptr; } + +bool ImmediateDrawer::ScissorToRenderTarget(const ImmediateDraw& immediate_draw, + uint32_t& out_left, + uint32_t& out_top, + uint32_t& out_width, + uint32_t& out_height) { + uint32_t render_target_width = ui_draw_context()->render_target_width(); + uint32_t render_target_height = ui_draw_context()->render_target_height(); + if (!immediate_draw.scissor) { + out_left = 0; + out_top = 0; + out_width = render_target_width; + out_height = render_target_height; + return render_target_width && render_target_height; + } + float render_target_width_float = float(render_target_width); + float render_target_height_float = float(render_target_height); + // Scale to render target coordinates, drop NaNs (by doing + // std::max(0.0f, variable) in this argument order), and clamp to the render + // target size, below which the values are representable as 16p8 fixed-point. + float scale_x = render_target_width / coordinate_space_width(); + float scale_y = render_target_height / coordinate_space_height(); + float x0_float = + std::min(render_target_width_float, + std::max(0.0f, immediate_draw.scissor_left * scale_x)); + float y0_float = + std::min(render_target_height_float, + std::max(0.0f, immediate_draw.scissor_top * scale_y)); + // Also make sure the size is non-negative. + float x1_float = + std::min(render_target_width_float, + std::max(x0_float, immediate_draw.scissor_right * scale_x)); + float y1_float = + std::min(render_target_height_float, + std::max(y0_float, immediate_draw.scissor_bottom * scale_y)); + // Top-left - include .5 (0.128 treated as 0 covered, 0.129 as 0 not covered). + int32_t x0 = (FloatToD3D11Fixed16p8(x0_float) + 127) >> 8; + int32_t y0 = (FloatToD3D11Fixed16p8(y0_float) + 127) >> 8; + // Bottom-right - exclude .5. + int32_t x1 = (FloatToD3D11Fixed16p8(x1_float) + 127) >> 8; + int32_t y1 = (FloatToD3D11Fixed16p8(y1_float) + 127) >> 8; + assert_true(x0 >= 0); + assert_true(y0 >= 0); + assert_true(x1 >= x0); + assert_true(y1 >= y0); + assert_true(x1 <= int32_t(render_target_width)); + assert_true(y1 <= int32_t(render_target_height)); + out_left = uint32_t(x0); + out_top = uint32_t(y0); + out_width = uint32_t(x1 - x0); + out_height = uint32_t(y1 - y0); + return x1 > x0 && y1 > y0; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/immediate_drawer.h b/src/xenia/ui/immediate_drawer.h index 544f16aa1..48bca319c 100644 --- a/src/xenia/ui/immediate_drawer.h +++ b/src/xenia/ui/immediate_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -12,11 +12,11 @@ #include +#include "xenia/ui/presenter.h" + namespace xe { namespace ui { -class GraphicsContext; - // Describes the filter applied when sampling textures. enum class ImmediateTextureFilter { kNearest, @@ -80,21 +80,38 @@ struct ImmediateDraw { // True to enable scissoring using the region defined by scissor_rect. bool scissor = false; - // Scissoring region in framebuffer pixels as (x, y, w, h). - int scissor_rect[4] = {0}; + // Scissoring region in the coordinate space (if right < left or bottom < top, + // not drawing). + float scissor_left = 0.0f; + float scissor_top = 0.0f; + float scissor_right = 0.0f; + float scissor_bottom = 0.0f; }; class ImmediateDrawer { public: + ImmediateDrawer(const ImmediateDrawer& immediate_drawer) = delete; + ImmediateDrawer& operator=(const ImmediateDrawer& immediate_drawer) = delete; + virtual ~ImmediateDrawer() = default; + void SetPresenter(Presenter* new_presenter); + // Creates a new texture with the given attributes and R8G8B8A8 data. virtual std::unique_ptr CreateTexture( uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool is_repeated, const uint8_t* data) = 0; - // Begins drawing in immediate mode using the given projection matrix. - virtual void Begin(int render_target_width, int render_target_height) = 0; + // Begins drawing in immediate mode using the given projection matrix. The + // presenter that is currently attached to the immediate drawer, as the + // implementation may hold presenter-specific information such as UI + // submission indices. Pass 0 or a negative value as the coordinate space + // width or height to use raw render target pixel coordinates (or this will + // just be used as a safe fallback when with a non-zero-sized surface the + // coordinate space size becomes zero somehow). + virtual void Begin(UIDrawContext& ui_draw_context, + float coordinate_space_width, + float coordinate_space_height); // Starts a draw batch. virtual void BeginDrawBatch(const ImmediateDrawBatch& batch) = 0; // Draws one set of a batch. @@ -102,13 +119,33 @@ class ImmediateDrawer { // Ends a draw batch. virtual void EndDrawBatch() = 0; // Ends drawing in immediate mode and flushes contents. - virtual void End() = 0; + virtual void End(); protected: - ImmediateDrawer(GraphicsContext* graphics_context) - : graphics_context_(graphics_context) {} + ImmediateDrawer() = default; - GraphicsContext* graphics_context_ = nullptr; + Presenter* presenter() const { return presenter_; } + virtual void OnLeavePresenter() {} + virtual void OnEnterPresenter() {} + + // Available between Begin and End. + UIDrawContext* ui_draw_context() const { return ui_draw_context_; } + float coordinate_space_width() const { return coordinate_space_width_; } + float coordinate_space_height() const { return coordinate_space_height_; } + + // Converts and clamps the scissor in the immediate draw to render target + // coordinates. Returns whether the scissor contains any render target pixels + // (but a valid scissor is written even if false is returned). + bool ScissorToRenderTarget(const ImmediateDraw& immediate_draw, + uint32_t& out_left, uint32_t& out_top, + uint32_t& out_width, uint32_t& out_height); + + private: + Presenter* presenter_ = nullptr; + + UIDrawContext* ui_draw_context_ = nullptr; + float coordinate_space_width_; + float coordinate_space_height_; }; } // namespace ui diff --git a/src/xenia/ui/menu_item.cc b/src/xenia/ui/menu_item.cc index 5563b8760..225ca6444 100644 --- a/src/xenia/ui/menu_item.cc +++ b/src/xenia/ui/menu_item.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -62,9 +62,11 @@ void MenuItem::RemoveChild(MenuItem* child_item) { MenuItem* MenuItem::child(size_t index) { return children_[index].get(); } -void MenuItem::OnSelected(UIEvent* e) { +void MenuItem::OnSelected() { if (callback_) { callback_(); + // Note that this MenuItem might have been destroyed by the callback. + // Must not do anything with *this in this function from now on. } } diff --git a/src/xenia/ui/menu_item.h b/src/xenia/ui/menu_item.h index 8b61f040a..01bcbe5c5 100644 --- a/src/xenia/ui/menu_item.h +++ b/src/xenia/ui/menu_item.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -48,14 +48,18 @@ class MenuItem { const std::string& text() { return text_; } const std::string& hotkey() { return hotkey_; } + // If the menu is currently attached to a Window, changes to it (such as the + // elements and the enabled / disabled state) may be not reflected + // immediately - call Window::CompleteMainMenuItemsUpdate when the + // modifications are done. + void AddChild(MenuItem* child_item); void AddChild(std::unique_ptr child_item); void AddChild(MenuItemPtr child_item); void RemoveChild(MenuItem* child_item); MenuItem* child(size_t index); - virtual void EnableMenuItem(Window& window) = 0; - virtual void DisableMenuItem(Window& window) = 0; + virtual void SetEnabled(bool enabled) {} protected: MenuItem(Type type, const std::string& text, const std::string& hotkey, @@ -64,13 +68,17 @@ class MenuItem { virtual void OnChildAdded(MenuItem* child_item) {} virtual void OnChildRemoved(MenuItem* child_item) {} - virtual void OnSelected(UIEvent* e); + // This MenuItem may be destroyed as a result of the callback, don't do + // anything with it after the call. + void OnSelected(); Type type_; MenuItem* parent_item_; std::vector children_; std::string text_; std::string hotkey_; + + private: std::function callback_; }; diff --git a/src/xenia/ui/microprofile_drawer.cc b/src/xenia/ui/microprofile_drawer.cc index fb6588348..9680a492c 100644 --- a/src/xenia/ui/microprofile_drawer.cc +++ b/src/xenia/ui/microprofile_drawer.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,9 +10,10 @@ #include "xenia/ui/microprofile_drawer.h" #include +#include #include "xenia/base/math.h" -#include "xenia/ui/window.h" +#include "xenia/base/profiling.h" namespace xe { namespace ui { @@ -124,10 +125,8 @@ const uint8_t kFontData[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; -MicroprofileDrawer::MicroprofileDrawer(xe::ui::Window* window) - : window_(window), - graphics_context_(window->context()), - vertices_(kMaxVertices) { +MicroprofileDrawer::MicroprofileDrawer(ImmediateDrawer* immediate_drawer) + : immediate_drawer_(immediate_drawer), vertices_(kMaxVertices) { SetupFont(); } @@ -171,21 +170,21 @@ void MicroprofileDrawer::SetupFont() { } } - font_texture_ = graphics_context_->immediate_drawer()->CreateTexture( + font_texture_ = immediate_drawer_->CreateTexture( kFontTextureWidth, kFontTextureHeight, ImmediateTextureFilter::kNearest, false, reinterpret_cast(unpacked)); } -MicroprofileDrawer::~MicroprofileDrawer() = default; - -void MicroprofileDrawer::Begin() { - graphics_context_->immediate_drawer()->Begin(window_->scaled_width(), - window_->scaled_height()); +void MicroprofileDrawer::Begin(UIDrawContext& ui_draw_context, + uint32_t coordinate_space_width, + uint32_t coordinate_space_height) { + immediate_drawer_->Begin(ui_draw_context, float(coordinate_space_width), + float(coordinate_space_height)); } void MicroprofileDrawer::End() { Flush(); - graphics_context_->immediate_drawer()->End(); + immediate_drawer_->End(); } ImmediateVertex* MicroprofileDrawer::BeginVertices( @@ -203,7 +202,6 @@ ImmediateVertex* MicroprofileDrawer::BeginVertices( void MicroprofileDrawer::EndVertices() {} void MicroprofileDrawer::Flush() { - auto drawer = graphics_context_->immediate_drawer(); if (!vertex_count_) { return; } @@ -211,15 +209,15 @@ void MicroprofileDrawer::Flush() { ImmediateDrawBatch batch; batch.vertices = vertices_.data(); batch.vertex_count = vertex_count_; - drawer->BeginDrawBatch(batch); + immediate_drawer_->BeginDrawBatch(batch); ImmediateDraw draw; draw.primitive_type = current_primitive_type_; draw.count = vertex_count_; draw.texture = font_texture_.get(); - drawer->Draw(draw); + immediate_drawer_->Draw(draw); - drawer->EndDrawBatch(); + immediate_drawer_->EndDrawBatch(); vertex_count_ = 0; } @@ -323,8 +321,8 @@ void MicroprofileDrawer::DrawLine2D(uint32_t count, float* vertices, EndVertices(); } -void MicroprofileDrawer::DrawText(int x, int y, uint32_t color, - const char* text, int text_length) { +void MicroprofileDrawer::DrawTextString(int x, int y, uint32_t color, + const char* text, int text_length) { if (!text_length) { return; } diff --git a/src/xenia/ui/microprofile_drawer.h b/src/xenia/ui/microprofile_drawer.h index 1f285e1bc..5313935dd 100644 --- a/src/xenia/ui/microprofile_drawer.h +++ b/src/xenia/ui/microprofile_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_UI_MICROPROFILE_DRAWER_H_ #define XENIA_UI_MICROPROFILE_DRAWER_H_ +#include #include #include @@ -18,9 +19,6 @@ namespace xe { namespace ui { -class GraphicsContext; -class Window; - class MicroprofileDrawer { public: enum class BoxType { @@ -28,15 +26,17 @@ class MicroprofileDrawer { kFlat = 1, // MicroProfileBoxTypeFlat }; - MicroprofileDrawer(Window* window); - ~MicroprofileDrawer(); + // Initially hidden. + MicroprofileDrawer(ImmediateDrawer* immediate_drawer); - void Begin(); + void Begin(UIDrawContext& ui_draw_context, uint32_t coordinate_space_width, + uint32_t coordinate_space_height); void End(); void DrawBox(int x0, int y0, int x1, int y1, uint32_t color, BoxType type); void DrawLine2D(uint32_t count, float* vertices, uint32_t color); - void DrawText(int x, int y, uint32_t color, const char* text, - int text_length); + // The name DrawTextString collides with DrawText in Windows. + void DrawTextString(int x, int y, uint32_t color, const char* text, + int text_length); protected: void SetupFont(); @@ -46,8 +46,7 @@ class MicroprofileDrawer { void EndVertices(); void Flush(); - Window* window_ = nullptr; - GraphicsContext* graphics_context_ = nullptr; + ImmediateDrawer* immediate_drawer_; std::vector vertices_; int vertex_count_ = 0; diff --git a/src/xenia/ui/premake5.lua b/src/xenia/ui/premake5.lua index 540c27154..3b9e482c4 100644 --- a/src/xenia/ui/premake5.lua +++ b/src/xenia/ui/premake5.lua @@ -18,3 +18,8 @@ project("xenia-ui") filter("platforms:Android-*") -- Exports JNI functions. wholelib("On") + + filter("platforms:Windows") + links({ + "DXGI", + }) diff --git a/src/xenia/ui/presenter.cc b/src/xenia/ui/presenter.cc new file mode 100644 index 000000000..661a37a8a --- /dev/null +++ b/src/xenia/ui/presenter.cc @@ -0,0 +1,1446 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/presenter.h" + +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/cvar.h" +#include "xenia/base/logging.h" +#include "xenia/base/platform.h" +#include "xenia/ui/window.h" + +#if XE_PLATFORM_WIN32 +#include "xenia/ui/window_win.h" +#endif + +// On Windows, InvalidateRect causes WM_PAINT to be sent quite quickly, so +// presenting from the thread refreshing the guest output is not absolutely +// necessary, but still may be nice for bypassing the scheduling and the +// message queue. +// On Android and GTK, the frame rate of draw events is limited to the display +// refresh rate internally, so for the lowest latency especially in case the +// refresh rates differ significantly on the guest and the host (like 30/60 Hz +// presented to 144 Hz), drawing from the guest output refreshing thread is +// highly desirable. Presenting directly from the GPU emulation thread also +// makes debugging GPU emulation easier with external tools, as presenting in +// most cases happens exactly between emulation frames. +DEFINE_bool( + host_present_from_non_ui_thread, true, + "Allow the GPU emulation thread to present the guest output to the host " + "surface directly instead of requesting the UI thread to do so through the " + "host window system.", + "Display"); + +DEFINE_bool( + present_render_pass_clear, true, + "On graphics backends where this is supported, use the clear render pass " + "load operation in presentation instead of clear commands clearing only " + "the letterbox area.", + "Display"); + +DEFINE_bool( + present_letterbox, true, + "Maintain aspect ratio when stretching by displaying bars around the image " + "when there's no more overscan area to crop out.", + "Display"); +// https://github.com/MonoGame/MonoGame/issues/4697#issuecomment-217779403 +// Using the value from DirectXTK (5% cropped out from each side, thus 90%), +// which is not exactly the Xbox One title-safe area, but close, and within the +// action-safe area: +// https://github.com/microsoft/DirectXTK/blob/1e80a465c6960b457ef9ab6716672c1443a45024/Src/SimpleMath.cpp#L144 +// XNA TitleSafeArea is 80%, but it's very conservative, designed for CRT, and +// is the title-safe area rather than the action-safe area. +// 90% is also exactly the fraction of 16:9 height in 16:10. +DEFINE_int32( + present_safe_area_x, 90, + "Percentage of the image width that can be kept when presenting to " + "maintain aspect ratio without letterboxing or stretching.", + "Display"); +DEFINE_int32( + present_safe_area_y, 90, + "Percentage of the image height that can be kept when presenting to " + "maintain aspect ratio without letterboxing or stretching.", + "Display"); + +namespace xe { +namespace ui { + +void Presenter::FatalErrorHostGpuLossCallback( + [[maybe_unused]] bool is_responsible, + [[maybe_unused]] bool statically_from_ui_thread) { + xe::FatalError("Graphics device lost (probably due to an internal error)"); +} + +Presenter::~Presenter() { + // No intrusive lifetime management must be performed from UI drawers - defer + // it if needed. + assert_false(is_executing_ui_drawers_); + +#if XE_PLATFORM_WIN32 + if (dxgi_ui_tick_thread_.joinable()) { + { + std::scoped_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + dxgi_ui_tick_thread_shutdown_ = true; + } + dxgi_ui_tick_control_condition_.notify_all(); + dxgi_ui_tick_thread_.join(); + } +#endif // XE_PLATFORM + + if (window_) { + Window* old_window = window_; + // Null the pointer to prevent an infinite loop between SetPresenter and + // SetWindowSurfaceFromUIThread calling each other. + window_ = nullptr; + old_window->SetPresenter(nullptr); + } +} + +void Presenter::SetWindowSurfaceFromUIThread(Window* new_window, + Surface* new_surface) { + // No intrusive lifetime management must be performed from UI drawers - defer + // it if needed. + assert_false(is_executing_ui_drawers_); + + // There can't be a valid surface pointer without a window, as a surface is + // created and owned by the window. + assert_false(new_surface && !new_window); + + if (window_ == new_window && (!window_ || surface_ == new_surface)) { + // Nothing has changed (or a recursive SetWindowSurfaceFromUIThread > + // SetPresenter > SetWindowSurfaceFromUIThread call). + return; + } + + // Disconnect from the current surface. + if (surface_) { + // Take ownership of painting, and also stop accepting paint requests from + // the guest output thread - the window (which is required for making them) + // may be going away, and there will be a forced paint when the connection + // becomes available. + SetPaintModeFromUIThread(PaintMode::kNone); + DisconnectPaintingFromSurfaceFromUIThread( + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange); + surface_ = nullptr; + UpdateSurfaceMonitorFromUIThread(true); + } + + if (window_ != new_window) { + // The window pointer may be accessed by the guest output thread if painting + // is possible (or was possible, but the paint attempt has resulted in the + // implementation reporting that the connection has become outdated). + // However, a painting connection is currently not established at all, so + // it's safe to modify the window pointer here. + + // Detach from the old window if attaching to a different one or just + // detaching. SetPresenter for the new window might have been called without + // it having been called with nullptr for the old window. + if (window_) { + Window* old_window = window_; + // Null the pointer to prevent an infinite loop between SetPresenter and + // SetWindowSurfaceFromUIThread calling each other. + window_ = nullptr; + old_window->SetPresenter(nullptr); + } + + // Attach to the new one. + // This function is called from SetPresenter - don't need to notify the + // window of this, as it itself has triggered this. + window_ = new_window; + } + + if (new_surface) { + assert_true(paint_mode_ == PaintMode::kNone); + surface_ = new_surface; + UpdateSurfaceMonitorFromUIThread(true); + assert_true(surface_paint_connection_state_ == + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange); + bool request_repaint; + UpdateSurfacePaintConnectionFromUIThread(&request_repaint, true); + // Request to paint as soon as possible in the UI thread if connected + // successfully. + if (request_repaint) { + RequestPaintOrConnectionRecoveryViaWindow(true); + } + } +} + +void Presenter::OnSurfaceMonitorUpdateFromUIThread( + bool old_monitor_potentially_disconnected) { + // No intrusive lifetime management must be performed from UI drawers - defer + // it if needed. + assert_false(is_executing_ui_drawers_); + + if (!surface_) { + return; + } + + UpdateSurfaceMonitorFromUIThread(old_monitor_potentially_disconnected); +} + +void Presenter::OnSurfaceResizeFromUIThread() { + // No intrusive lifetime management must be performed from UI drawers - defer + // it if needed. + assert_false(is_executing_ui_drawers_); + + if (!surface_) { + return; + } + + // Let the UI thread take ownership of painting (so the connection can be + // updated) in a smooth way - downgrade to kUIThreadOnRequest rather than + // kNone, because a forced repaint may not be necessary if, for example, the + // size internally turns out to be the same after the update, and in this case + // the current image may be kept - but the new one must not be missed either + // if it becomes available during the resize. + if (paint_mode_ == PaintMode::kGuestOutputThreadImmediately) { + SetPaintModeFromUIThread(PaintMode::kUIThreadOnRequest); + } + + bool request_repaint; + UpdateSurfacePaintConnectionFromUIThread(&request_repaint, true); + + // Request to repaint as soon as possible in the UI thread if needed. + if (request_repaint) { + RequestPaintOrConnectionRecoveryViaWindow(true); + } +} + +void Presenter::PaintFromUIThread(bool force_paint) { + // If there is no surface, this will be a no-op, nothing outdated, nothing to + // paint. However, an explicit monitor check is needed because UI framerate + // limiting may be tied to signals from the OS for the monitor - but painting + // may still occur, for instance, if drawing to a composition surface in the + // OS (which will still be live even if the window goes outside any monitor). + // But a surface check still won't cause harm, for simplicity. + if (!InSurfaceOnMonitorFromUIThread()) { + return; + } + + // Defer changes to the paint mode as well as window paint requests, and do + // them in this function so they're consistent with the assumptions made here. + assert_false(is_in_ui_thread_paint_); + is_in_ui_thread_paint_ = true; + request_guest_output_paint_after_current_ui_thread_paint_ = false; + request_ui_paint_after_current_ui_thread_paint_ = false; + + // Actualize the connection if the UI needs to be drawn if there was some + // explicit paint request (the guest output has been refreshed, and the guest + // output thread was asked not to present directly due as the UI needs to be + // drawn, or some surface state change has happened so the guest output needs + // to be displayed as soon as possible without waiting for the guest to + // refresh it, or the guest output thread has been notified that the + // connection has become outdated and has requested the UI thread to + // reconnect). + bool draw_ui = !ui_drawers_.empty(); + bool do_paint = force_paint || draw_ui; + // Reset ui_thread_paint_requested_ unconditionally also, regardless of + // whether the UI needs to be drawn - the flag may be set to try reconnecting, + // for example. + if (ui_thread_paint_requested_.exchange(false, std::memory_order_relaxed)) { + do_paint = true; + } + PaintResult paint_result = PaintResult::kNotPresented; + bool request_repaint_at_tick = false; + bool request_repaint_immediately = false; + if (do_paint) { + // Take ownership of painting if it's currently owned by the guest output + // thread (downgrade from kGuestOutputThreadImmediately to + // kUIThreadOnRequest - not to kNone so if during this paint a new guest + // output frame is generated, the notification will still be sent to the UI + // thread rather than dropped, so the frame won't be skipped). This is + // needed to be able not only to paint, but also to try to recover from an + // outdated surface. + if (paint_mode_ == PaintMode::kGuestOutputThreadImmediately) { + SetPaintModeFromUIThread(PaintMode::kUIThreadOnRequest); + } + // Try to recover from the connection becoming outdated in the previous + // paint. + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedOutdated) { + UpdateSurfacePaintConnectionFromUIThread(nullptr, false); + } + // If still paintable or recovered successfully, paint. + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable) { + // The paint mode might have been set to kNone when the connection was + // marked as outdated last time. Or, if wasn't reconnecting, there was + // some other incorrect situation that caused the paint mode to be set to + // kNone for an active connection. Make sure that the current paint mode + // is consistent with painting from the UI thread. + SetPaintModeFromUIThread(PaintMode::kUIThreadOnRequest); + + // Limit the frame rate of the UI, usually to the monitor refresh rate, + // in a way so that the UI won't be stealing all the remaining GPU + // resources if it's repainted continuously, and the window system itself + // doesn't limit the frame rate. + WaitForUITickFromUIThread(); + + paint_result = PaintAndPresent(draw_ui); + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedOutdated) { + // Request another PaintFromUIThread which will try to recover from the + // outdated connection in the next frame (not immediately, so the + // windowing system has some time to prepare what may be required to + // recover from it, such as to send a resize event). + request_repaint_immediately = true; + } + } + // If can't paint anymore, notify the paint mode refresh below (which is not + // guaranteed to have access to have ownership of painting as it's taken + // here only conditionally, thus can't know whether the connection is + // actually in a paintable state). + if (surface_paint_connection_state_ != + SurfacePaintConnectionState::kConnectedPaintable) { + SetPaintModeFromUIThread(PaintMode::kNone); + } + } + + // Transfer the ownership of painting back to the guest output thread if it + // was taken or if needed for any reason (however, it's taken conditionally - + // no guarantees that the actual connection state is accessible here, so only + // checking whether the mode is not kNone currently, not the connection + // state), and overall synchronize the state taking into account both what has + // been done in this function and what could have been done by the UI drawer + // callbacks. + if (paint_mode_ != PaintMode::kNone) { + SetPaintModeFromUIThread(GetDesiredPaintModeFromUIThread(true)); + } + is_in_ui_thread_paint_ = false; + + // Check if the device has been lost. There's no point in requesting repaint + // if it has happened anyway, it won't be possible to satisfy such request + // with the current Presenter. + if (paint_result == PaintResult::kGpuLostExternally || + paint_result == PaintResult::kGpuLostResponsible) { + if (host_gpu_loss_callback_) { + host_gpu_loss_callback_(paint_result == PaintResult::kGpuLostResponsible, + true); + } + // The loss callback might have destroyed the presenter, must not do + // anything with `this` anymore. + return; + } + + // Request refresh if needed. + // Can't check the exact paintability as the connection state may currently + // be owned by the guest output thread, so check conservatively via + // paint_mode_. + if (paint_mode_ != PaintMode::kNone) { + // Immediately paint the guest output if requested explicitly or if the UI + // has hidden itself. + if (request_guest_output_paint_after_current_ui_thread_paint_ || + (draw_ui && ui_drawers_.empty())) { + request_repaint_immediately = true; + } + if (request_ui_paint_after_current_ui_thread_paint_ && + !ui_drawers_.empty()) { + request_repaint_at_tick = true; + } + } + if (request_repaint_at_tick || request_repaint_immediately) { + RequestPaintOrConnectionRecoveryViaWindow(request_repaint_immediately); + } +} + +bool Presenter::RefreshGuestOutput( + uint32_t frontbuffer_width, uint32_t frontbuffer_height, + uint32_t screen_width, uint32_t screen_height, + std::function refresher) { + GuestOutputProperties& writable_properties = + guest_output_properties_[guest_output_mailbox_writable_]; + writable_properties.frontbuffer_width = frontbuffer_width; + writable_properties.frontbuffer_height = frontbuffer_height; + writable_properties.screen_width = screen_width; + writable_properties.screen_height = screen_height; + writable_properties.is_8bpc = false; + bool is_active = writable_properties.IsActive(); + if (is_active) { + if (!RefreshGuestOutputImpl(guest_output_mailbox_writable_, + frontbuffer_width, frontbuffer_height, + refresher, writable_properties.is_8bpc)) { + // If failed to refresh, don't send the currently writable image to the + // mailbox as it may be in an undefined state. Don't disable the guest + // output either though because the failure may be something transient. + return false; + } + guest_output_active_last_refresh_ = true; + } else { + // Request presenting a blank image if there was a true image previously, + // but not now. + if (!guest_output_active_last_refresh_) { + return false; + } + guest_output_active_last_refresh_ = false; + } + + // Make the new image the next to present on the host (the "ready" one), + // replacing the one already specified as the next (dropping it instead of + // enqueueing the new image after it) to achieve the lowest latency (also, + // after switching from UI thread painting to doing it in the guest output + // thread, will immediately recover to having the latest frame always sent to + // the host present call on the CPU and all frames reaching a present call). + uint32_t last_acquired_and_ready = + guest_output_mailbox_acquired_and_ready_.load(std::memory_order_relaxed); + // Desired acquired = current acquired (changed only by the consumers). + // Desired ready = current writable. + // memory_order_acq_rel to acquire the new writable image and to release the + // current one (to let the consumers take it, from ready to acquired). + while (!guest_output_mailbox_acquired_and_ready_.compare_exchange_weak( + last_acquired_and_ready, + (last_acquired_and_ready & 3) | (guest_output_mailbox_writable_ << 2), + std::memory_order_acq_rel, std::memory_order_relaxed)) { + } + // Now, it's known that `ready == writable` on the host presentation side. + // Take the next `writable` with this assumption about its current value in + // mind. + uint32_t last_acquired = last_acquired_and_ready & 3; + if (last_acquired == guest_output_mailbox_writable_) { + // The new image has already been acquired by the time the compare-exchange + // loop has finished (acquired == ready == currently writable). + // It's a valid situation from the ownership perspective, and the semantics + // of the weak compare-exchange explicitly permit spurious `false` results. + // (3 - a - b) % 3 cannot be used here, as (3 - a - a) % 3 results in `a` - + // the same index. + // Take any free image. Preferably using + 1, not ^ 1, so if the guest needs + // to await any GPU work referencing the image, it will wait for the frame 3 + // frames ago, not 2, if this happens repeatedly. + guest_output_mailbox_writable_ = (guest_output_mailbox_writable_ + 1) % 3; + } else { + // Take the image other than the last acquired one and the new one, + // currently not accessible to the host presentation. + guest_output_mailbox_writable_ = + (3 - last_acquired - guest_output_mailbox_writable_) % 3; + } + + // Trigger the presentation on the host. + PaintResult paint_result = PaintResult::kNotPresented; + { + std::lock_guard paint_mode_mutex_lock(paint_mode_mutex_); + switch (paint_mode_) { + case PaintMode::kNone: + // Neither painting nor window paint requesting is accessible. + break; + case PaintMode::kUIThreadOnRequest: + // Only window paint requesting is accessible. + RequestPaintOrConnectionRecoveryViaWindow(true); + break; + case PaintMode::kGuestOutputThreadImmediately: + // Both painting and window paint requesting are accessible. + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable) { + paint_result = PaintAndPresent(false); + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedOutdated) { + RequestPaintOrConnectionRecoveryViaWindow(true); + } + } + break; + } + } + // Handle GPU loss when not in the middle of the function anymore, and + // lifecycle management from the GPU loss callback is fine on the UI thread. + if (host_gpu_loss_callback_) { + if (paint_result == PaintResult::kGpuLostResponsible) { + host_gpu_loss_callback_(true, false); + } else if (paint_result == PaintResult::kGpuLostExternally) { + host_gpu_loss_callback_(false, false); + } + } + + return is_active; +} + +void Presenter::SetGuestOutputPaintConfigFromUIThread( + const GuestOutputPaintConfig& new_config) { + // For simplicity, this may be called externally repeatedly. + // Lock the mutex only when something has been modified, and also don't + // request UI thread guest output redraws when not needed. + bool modified = false; + bool request_repaint = false; + if (guest_output_paint_config_.GetEffect() != new_config.GetEffect()) { + modified = true; + request_repaint = true; + } + if (guest_output_paint_config_.GetFsrSharpnessReduction() != + new_config.GetFsrSharpnessReduction()) { + modified = true; + if (new_config.GetEffect() == GuestOutputPaintConfig::Effect::kFsr) { + request_repaint = true; + } + } + if (guest_output_paint_config_.GetCasAdditionalSharpness() != + new_config.GetCasAdditionalSharpness()) { + modified = true; + if (new_config.GetEffect() == GuestOutputPaintConfig::Effect::kCas || + new_config.GetEffect() == GuestOutputPaintConfig::Effect::kFsr) { + request_repaint = true; + } + } + if (guest_output_paint_config_.GetDither() != new_config.GetDither()) { + modified = true; + request_repaint = true; + } + if (modified) { + { + std::unique_lock config_lock( + guest_output_paint_config_mutex_); + guest_output_paint_config_ = new_config; + } + // Coarsely check the availability of painting and of the window (for + // calling RequestPaint) via paint_mode_ because the actual painting + // connection state may currently be owned not by the UI thread. + if (request_repaint && paint_mode_ != PaintMode::kNone) { + if (is_in_ui_thread_paint_) { + // Defer until the end of the current paint if called from, for + // instance, a UI drawer. + request_guest_output_paint_after_current_ui_thread_paint_ = true; + } else { + RequestPaintOrConnectionRecoveryViaWindow(true); + } + } + } +} + +void Presenter::AddUIDrawerFromUIThread(UIDrawer* drawer, size_t z_order) { + assert_not_null(drawer); + // Obtain whether the iterator list was empty before erasing in case of + // replacing with a new entry with a different Z order happens. + bool drawers_were_empty = ui_drawers_.empty(); + uint64_t drawer_last_draw = UINT64_MAX; + // Check if already added. + for (auto it_existing = ui_drawers_.begin(); it_existing != ui_drawers_.end(); + ++it_existing) { + if (it_existing->second.drawer != drawer) { + continue; + } + if (it_existing->first == z_order) { + return; + } + // Keep the same last draw index to prevent the drawer from being executed + // twice if increasing its Z order during the drawer loop. + drawer_last_draw = it_existing->second.last_draw; + // If removing the drawer that is the next in the current drawer loop, skip + // it (in a multimap, only one element iterator is invalidated). + if (is_executing_ui_drawers_ && ui_draw_next_iterator_ == it_existing) { + ++ui_draw_next_iterator_; + } + ui_drawers_.erase(it_existing); + break; + } + auto it_new = + ui_drawers_.emplace(z_order, UIDrawerReference(drawer, drawer_last_draw)); + // If adding to the Z layer currently being processed (for drawing, from the + // lowest to the highest), or to layers in between the current and the + // previously next, make sure the new drawer is executed too. + if (is_executing_ui_drawers_ && z_order >= ui_draw_current_z_order_ && + (ui_draw_next_iterator_ == ui_drawers_.end() || + z_order < ui_draw_next_iterator_->first)) { + ui_draw_next_iterator_ = it_new; + } + HandleUIDrawersChangeFromUIThread(drawers_were_empty); +} + +void Presenter::RemoveUIDrawerFromUIThread(UIDrawer* drawer) { + assert_not_null(drawer); + for (auto it_existing = ui_drawers_.begin(); it_existing != ui_drawers_.end(); + ++it_existing) { + if (it_existing->second.drawer != drawer) { + continue; + } + // If removing the drawer that is the next in the current drawer loop, skip + // it (in a multimap, only one element iterator is invalidated). + if (is_executing_ui_drawers_ && ui_draw_next_iterator_ == it_existing) { + ++ui_draw_next_iterator_; + } + ui_drawers_.erase(it_existing); + HandleUIDrawersChangeFromUIThread(false); + return; + } +} + +void Presenter::RequestUIPaintFromUIThread() { + if (is_in_ui_thread_paint_) { + // The paint request will be done once in the end of PaintFromUIThread + // according to the actual state at the moment that happens. It's common for + // drawers to call this (even every frame), and no need to do too many OS + // paint request calls. + request_ui_paint_after_current_ui_thread_paint_ = true; + return; + } + // The connection state may be owned by the guest output thread now rather + // than the UI thread, check whether it's not pointless to make the request + // coarsely via paint_mode_. + if (!ui_drawers_.empty() && paint_mode_ != PaintMode::kNone) { + // The window must be present, otherwise the conditions wouldn't have been + // met. + window_->RequestPaint(); + } +} + +bool Presenter::InitializeCommonSurfaceIndependent() { + // Initialize UI frame rate limiting. +#if XE_PLATFORM_WIN32 + dxgi_ui_tick_thread_ = std::thread(&Presenter::DXGIUITickThread, this); +#endif // XE_PLATFORM + + return true; +} + +std::unique_lock Presenter::ConsumeGuestOutput( + uint32_t& mailbox_index_or_max_if_inactive_out, + GuestOutputProperties* properties_out, + GuestOutputPaintConfig* paint_config_out) { + if (paint_config_out) { + // Get the up-to-date guest output paint configuration settings set by the + // UI thread. + std::unique_lock config_lock(guest_output_paint_config_mutex_); + *paint_config_out = guest_output_paint_config_; + } + + // Lock the mutex to make sure the image that will be acquired now is owned + // exclusively by the calling thread for the time while this mutex is still + // locked (it needs to be held by the consumer while working with anything + // that depends on the image now being acquired or its index in the mailbox). + std::unique_lock consumer_lock( + guest_output_mailbox_consumer_mutex_); + // Acquire the up-to-date ready guest image (may be new, in this case the last + // acquired one will be released, or still the same or no refresh has happened + // since the last consumption). + // memory_order_relaxed here because the ready index from this load will be + // used directly only if it's the same as during the last consumption - thus + // the image has already been acquired previously, no need for + // memory_order_acquire (if the image has been acquired by a different + // consumer though, the consumer mutex performs memory access ordering). + uint32_t old_acquired_and_ready = + guest_output_mailbox_acquired_and_ready_.load(std::memory_order_relaxed); + // Desired acquired = current ready. + // Desired ready = current ready (changed only by the producer). + uint32_t desired_acquired_and_ready = + (old_acquired_and_ready & ~uint32_t(3)) | (old_acquired_and_ready >> 2); + // Either the same image as during the last consumption, or a new one, is + // satisfying. However, if it's new, using memory_order_acq_rel to acquire the + // new ready image (to make it acquired) and to release the old acquired image + // (to let the producer take it as writable). + while (old_acquired_and_ready != desired_acquired_and_ready && + !guest_output_mailbox_acquired_and_ready_.compare_exchange_weak( + old_acquired_and_ready, desired_acquired_and_ready, + std::memory_order_acq_rel, std::memory_order_relaxed)) { + desired_acquired_and_ready = + (old_acquired_and_ready & ~uint32_t(3)) | (old_acquired_and_ready >> 2); + } + uint32_t mailbox_index = desired_acquired_and_ready & 3; + // Give the current acquired image to the caller, or UINT32_MAX if it's + // inactive. + const GuestOutputProperties& properties = + guest_output_properties_[mailbox_index]; + mailbox_index_or_max_if_inactive_out = + properties.IsActive() ? mailbox_index : UINT32_MAX; + if (properties_out) { + *properties_out = properties; + } + return std::move(consumer_lock); +} + +Presenter::GuestOutputPaintFlow Presenter::GetGuestOutputPaintFlow( + const GuestOutputProperties& properties, uint32_t host_rt_width, + uint32_t host_rt_height, uint32_t max_rt_width, uint32_t max_rt_height, + const GuestOutputPaintConfig& config) const { + GuestOutputPaintFlow flow = {}; + + // FIXME(Triang3l): Configuration variables racing with per-game config + // loading. + + assert_not_zero(max_rt_width); + assert_not_zero(max_rt_height); + + // Initialize one clear rectangle for the case of drawing no guest output, for + // consistency with fewer state dependencies. + flow.letterbox_clear_rectangle_count = 1; + flow.letterbox_clear_rectangles[0].width = host_rt_width; + flow.letterbox_clear_rectangles[0].height = host_rt_height; + + // For safety such as division by zero prevention. + if (!properties.IsActive() || !host_rt_width || !host_rt_height || + !surface_width_in_paint_connection_ || + !surface_height_in_paint_connection_) { + return flow; + } + + flow.properties = properties; + + // Multiplication-division rounding to the nearest. + auto rescale_unsigned = [](uint32_t value, uint32_t new_scale, + uint32_t old_scale) -> uint32_t { + return uint32_t((uint64_t(value) * new_scale + (old_scale >> 1)) / + old_scale); + }; + auto rescale_signed = [](int32_t value, uint32_t new_scale, + uint32_t old_scale) -> int32_t { + // Plus old_scale / 2 for positive values, minus old_scale / 2 for + // negative values for consistent rounding for both positive and + // negative values (as the `/` operator rounds towards zero). + // Example: + // (-3 - 1) / 3 == -1 + // (-2 - 1) / 3 == -1 + // (-1 - 1) / 3 == 0 + // --- + // (0 + 1) / 3 == 0 + // (1 + 1) / 3 == 0 + // (2 + 1) / 3 == 1 + return int32_t((int64_t(value) * new_scale + + int32_t(old_scale >> 1) * (value < 0 ? -1 : 1)) / + old_scale); + }; + + // Final output location and dimensions. + // All host location calculations are DPI-independent, conceptually depending + // only on the aspect ratios, not the absolute values. + uint32_t output_width, output_height; + if (uint64_t(surface_width_in_paint_connection_) * properties.screen_height > + uint64_t(properties.screen_width) * surface_height_in_paint_connection_) { + // The window is wider that the source - crop along Y to preserve the aspect + // ratio while stretching throughout the entire surface's width, then limit + // the Y cropping via letterboxing or stretching along X. + uint32_t present_safe_area; + if (cvars::present_safe_area_y > 0 && cvars::present_safe_area_y < 100) { + present_safe_area = uint32_t(cvars::present_safe_area_y); + } else { + present_safe_area = 100; + } + // Scale the desired width by the H:W aspect ratio (inverse of W:H) to get + // the height. + output_height = + rescale_unsigned(surface_width_in_paint_connection_, + properties.screen_height, properties.screen_width); + bool letterbox = false; + if (output_height * present_safe_area > + surface_height_in_paint_connection_ * 100) { + // Don't crop out more than the safe area margin - letterbox or stretch. + output_height = rescale_unsigned(surface_height_in_paint_connection_, 100, + present_safe_area); + letterbox = true; + } + if (letterbox && cvars::present_letterbox) { + output_width = rescale_unsigned( + properties.screen_width, surface_height_in_paint_connection_ * 100, + properties.screen_height * present_safe_area); + // output_width might have been rounded up already by rescale_unsigned, so + // rounding down in this division. + flow.output_x = (int32_t(surface_width_in_paint_connection_) - + int32_t(output_width)) / + 2; + } else { + output_width = surface_width_in_paint_connection_; + flow.output_x = 0; + } + // output_height might have been rounded up already by rescale_unsigned, so + // rounding down in this division. + flow.output_y = (int32_t(surface_height_in_paint_connection_) - + int32_t(output_height)) / + 2; + } else { + // The window is taller that the source - crop along X to preserve the + // aspect ratio while stretching throughout the entire surface's height, + // then limit the X cropping via letterboxing or stretching along Y. + uint32_t present_safe_area; + if (cvars::present_safe_area_x > 0 && cvars::present_safe_area_x < 100) { + present_safe_area = uint32_t(cvars::present_safe_area_x); + } else { + present_safe_area = 100; + } + // Scale the desired height by the W:H aspect ratio to get the width. + output_width = + rescale_unsigned(surface_height_in_paint_connection_, + properties.screen_width, properties.screen_height); + bool letterbox = false; + if (output_width * present_safe_area > + surface_width_in_paint_connection_ * 100) { + // Don't crop out more than the safe area margin - letterbox or stretch. + output_width = rescale_unsigned(surface_width_in_paint_connection_, 100, + present_safe_area); + letterbox = true; + } + if (letterbox && cvars::present_letterbox) { + output_height = rescale_unsigned( + properties.screen_height, surface_width_in_paint_connection_ * 100, + properties.screen_width * present_safe_area); + // output_height might have been rounded up already by rescale_unsigned, + // so rounding down in this division. + flow.output_y = (int32_t(surface_height_in_paint_connection_) - + int32_t(output_height)) / + 2; + } else { + output_height = surface_height_in_paint_connection_; + flow.output_y = 0; + } + // output_width might have been rounded up already by rescale_unsigned, so + // rounding down in this division. + flow.output_x = + (int32_t(surface_width_in_paint_connection_) - int32_t(output_width)) / + 2; + } + + // Convert the location from surface pixels (which have 1:1 aspect ratio + // relatively to the physical display) to render target pixels (the render + // target size may be arbitrary with any aspect ratio, but if it's different + // than the surface size, the OS is expected to stretch it to the surface + // boundaries), preserving the aspect ratio. + if (host_rt_width != surface_width_in_paint_connection_) { + flow.output_x = rescale_signed(flow.output_x, host_rt_width, + surface_width_in_paint_connection_); + output_width = rescale_unsigned(output_width, host_rt_width, + surface_width_in_paint_connection_); + } + if (host_rt_height != surface_height_in_paint_connection_) { + flow.output_y = rescale_signed(flow.output_y, host_rt_height, + surface_height_in_paint_connection_); + output_height = rescale_unsigned(output_height, host_rt_height, + surface_height_in_paint_connection_); + } + + // The out-of-bounds checks are needed for correct letterbox calculations. + // Though this normally shouldn't happen, but in case of rounding issues with + // extreme values. + int32_t output_right = flow.output_x + int32_t(output_width); + int32_t output_bottom = flow.output_y + int32_t(output_height); + if (!output_width || !output_height || output_right <= 0 || + output_bottom <= 0 || flow.output_x >= int32_t(host_rt_width) || + flow.output_y >= int32_t(host_rt_height)) { + return flow; + } + + // The output image may have a part of it outside the final render target (if + // using the overscan area to stretch the image to the entire surface while + // preserving the guest aspect ratio if it differs from the host one, for + // instance). While the final render target size is known to be within the + // host render target / image size limit, the intermediate images may be + // larger than that as they include the overscan area that will be outside the + // screen. Make sure the intermediate images can't be larger than the maximum + // render target size. + uint32_t output_width_clamped = std::min(output_width, max_rt_width); + uint32_t output_height_clamped = std::min(output_height, max_rt_height); + + if (config.GetEffect() == GuestOutputPaintConfig::Effect::kCas || + config.GetEffect() == GuestOutputPaintConfig::Effect::kFsr) { + // FidelityFX Super Resolution and Contrast Adaptive Sharpening only work + // good for up to 2x2 upscaling due to the way they fetch texels. + // CAS is primarily a sharpening filter, not an upscaling one (its upscaling + // eliminates reduces blurriness, but doesn't preserve the shapes of edges, + // and executing it multiple times will only result in oversharpening. So, + // using it for scales only of up to 2x2, then simply stretching with + // bilinear filtering. + // EASU of FSR, however, preserves edges, it's not supposed to blur them or + // to make them jagged, so it can be executed multiple times - running + // multiple EASU passes for scale factors of over 2x2. + // Just one EASU pass rather than multiple for scaling to factors bigger + // than 2x2 (especially significantly bigger, such as 1152x640 to 3840x2160, + // or 3.333x3.375) results in blurry edges and an overall noisy look, + // multiple passes improve visual stability. + std::pair ffx_last_size; + if (flow.effect_count) { + ffx_last_size = flow.effect_output_sizes[flow.effect_count - 1]; + } else { + ffx_last_size.first = properties.frontbuffer_width; + ffx_last_size.second = properties.frontbuffer_height; + } + if (config.GetEffect() == GuestOutputPaintConfig::Effect::kFsr && + (ffx_last_size.first < output_width_clamped || + ffx_last_size.second < output_height_clamped)) { + // AMD FidelityFX Super Resolution - upsample along at least one axis. + // Using the output size clamped to the maximum render target size here as + // EASU will always write to intermediate images, and RCAS supports only + // 1:1. + uint32_t easu_max_passes = config.GetFsrMaxUpsamplingPasses(); + uint32_t easu_pass_count = 0; + while (easu_pass_count < easu_max_passes && + (ffx_last_size.first < output_width_clamped || + ffx_last_size.second < output_height_clamped)) { + ffx_last_size.first = + std::min(ffx_last_size.first * uint32_t(2), output_width_clamped); + ffx_last_size.second = + std::min(ffx_last_size.second * uint32_t(2), output_height_clamped); + assert_true(flow.effect_count < flow.effects.size()); + flow.effect_output_sizes[flow.effect_count] = ffx_last_size; + flow.effects[flow.effect_count++] = GuestOutputPaintEffect::kFsrEasu; + ++easu_pass_count; + } + assert_true(flow.effect_count < flow.effects.size()); + flow.effect_output_sizes[flow.effect_count] = ffx_last_size; + flow.effects[flow.effect_count++] = GuestOutputPaintEffect::kFsrRcas; + } else { + // AMD FidelityFX Contrast Adaptive Sharpening - sharpen or downsample, or + // upsample up to 2x2 if CAS is specified to be used for upscaling too. + // Using the unclamped output size as CAS may be the last pass - if a + // bilinear pass is needed afterwards, and the CAS pass will be writing to + // an intermediate image, the CAS pass output size will be clamped while + // adding the bilinear stretch. + std::pair pre_cas_size = ffx_last_size; + ffx_last_size.first = + std::min(ffx_last_size.first * uint32_t(2), output_width); + ffx_last_size.second = + std::min(ffx_last_size.second * uint32_t(2), output_height); + assert_true(flow.effect_count < flow.effects.size()); + flow.effect_output_sizes[flow.effect_count] = ffx_last_size; + flow.effects[flow.effect_count++] = + ffx_last_size == pre_cas_size ? GuestOutputPaintEffect::kCasSharpen + : GuestOutputPaintEffect::kCasResample; + } + } + + std::pair* last_pre_bilinear_effect_size = + flow.effect_count ? &flow.effect_output_sizes[flow.effect_count - 1] + : nullptr; + if (!last_pre_bilinear_effect_size || + last_pre_bilinear_effect_size->first != output_width || + last_pre_bilinear_effect_size->second != output_height) { + // If not using FidelityFX, or it has reached its upscaling capabilities, + // but more is needed, stretch via bilinear filtering. + // Clamp the output size of the last effect to the maximum render target + // size because it will go to an intermediate image now. + if (last_pre_bilinear_effect_size) { + // RCAS only works for 1:1, clamping must be done explicitly for FSR. + assert_false(flow.effects[flow.effect_count - 1] == + GuestOutputPaintEffect::kFsrRcas && + (last_pre_bilinear_effect_size->first > max_rt_width || + last_pre_bilinear_effect_size->second > max_rt_height)); + last_pre_bilinear_effect_size->first = + std::min(last_pre_bilinear_effect_size->first, max_rt_width); + last_pre_bilinear_effect_size->second = + std::min(last_pre_bilinear_effect_size->second, max_rt_height); + } + assert_true(flow.effect_count < flow.effects.size()); + flow.effect_output_sizes[flow.effect_count] = + std::make_pair(output_width, output_height); + flow.effects[flow.effect_count++] = GuestOutputPaintEffect::kBilinear; + } + + assert_not_zero(flow.effect_count); + + if (config.GetDither()) { + // Dithering must be applied only to the final effect since resampling and + // sharpening filters may considering the dithering noise features and + // amplify it. + GuestOutputPaintEffect& last_effect = flow.effects[flow.effect_count - 1]; + switch (last_effect) { + case GuestOutputPaintEffect::kBilinear: + // Dithering has no effect for 1:1 copying of a 8bpc image. + if (!properties.is_8bpc || flow.effect_count > 1 || + output_width != properties.frontbuffer_width || + output_height != properties.frontbuffer_height) { + last_effect = GuestOutputPaintEffect::kBilinearDither; + } + break; + case GuestOutputPaintEffect::kCasSharpen: + last_effect = GuestOutputPaintEffect::kCasSharpenDither; + break; + case GuestOutputPaintEffect::kCasResample: + last_effect = GuestOutputPaintEffect::kCasResampleDither; + break; + case GuestOutputPaintEffect::kFsrRcas: + last_effect = GuestOutputPaintEffect::kFsrRcasDither; + break; + default: + break; + } + } + +#ifndef NDEBUG + for (size_t i = 0; i + 1 < flow.effect_count; ++i) { + assert_true(CanGuestOutputPaintEffectBeIntermediate(flow.effects[i])); + } + assert_true( + CanGuestOutputPaintEffectBeFinal(flow.effects[flow.effect_count - 1])); +#endif + + // Calculate the letterbox geometry. + if (flow.effect_count) { + flow.letterbox_clear_rectangle_count = 0; + uint32_t letterbox_mid_top = uint32_t(std::max(flow.output_y, int32_t(0))); + // Top. + if (letterbox_mid_top) { + assert_true(flow.letterbox_clear_rectangle_count < + flow.letterbox_clear_rectangles.size()); + GuestOutputPaintFlow::ClearRectangle& letterbox_clear_rectangle_top = + flow.letterbox_clear_rectangles + [flow.letterbox_clear_rectangle_count++]; + letterbox_clear_rectangle_top.x = 0; + letterbox_clear_rectangle_top.y = 0; + letterbox_clear_rectangle_top.width = host_rt_width; + letterbox_clear_rectangle_top.height = letterbox_mid_top; + } + uint32_t letterbox_mid_bottom = + std::min(uint32_t(output_bottom), host_rt_height); + uint32_t letterbox_mid_height = letterbox_mid_bottom - letterbox_mid_top; + // Middle-left. + if (flow.output_x > 0) { + assert_true(flow.letterbox_clear_rectangle_count < + flow.letterbox_clear_rectangles.size()); + GuestOutputPaintFlow::ClearRectangle& letterbox_clear_rectangle_left = + flow.letterbox_clear_rectangles + [flow.letterbox_clear_rectangle_count++]; + letterbox_clear_rectangle_left.x = 0; + letterbox_clear_rectangle_left.y = letterbox_mid_top; + letterbox_clear_rectangle_left.width = uint32_t(flow.output_x); + letterbox_clear_rectangle_left.height = letterbox_mid_height; + } + // Middle-right. + if (uint32_t(output_right) < host_rt_width) { + assert_true(flow.letterbox_clear_rectangle_count < + flow.letterbox_clear_rectangles.size()); + GuestOutputPaintFlow::ClearRectangle& letterbox_clear_rectangle_right = + flow.letterbox_clear_rectangles + [flow.letterbox_clear_rectangle_count++]; + letterbox_clear_rectangle_right.x = uint32_t(output_right); + letterbox_clear_rectangle_right.y = letterbox_mid_top; + letterbox_clear_rectangle_right.width = + host_rt_width - uint32_t(output_right); + letterbox_clear_rectangle_right.height = letterbox_mid_height; + } + // Bottom. + if (letterbox_mid_bottom < host_rt_height) { + assert_true(flow.letterbox_clear_rectangle_count < + flow.letterbox_clear_rectangles.size()); + GuestOutputPaintFlow::ClearRectangle& letterbox_clear_rectangle_top = + flow.letterbox_clear_rectangles + [flow.letterbox_clear_rectangle_count++]; + letterbox_clear_rectangle_top.x = 0; + letterbox_clear_rectangle_top.y = letterbox_mid_bottom; + letterbox_clear_rectangle_top.width = host_rt_width; + letterbox_clear_rectangle_top.height = + host_rt_height - letterbox_mid_bottom; + } + } + + return flow; +} + +void Presenter::ExecuteUIDrawersFromUIThread(UIDrawContext& ui_draw_context) { + // May be called by the implementations only when requested. + assert_true(is_in_ui_thread_paint_); + // Drawers can add or remove drawers (including themselves), need to ensure + // iterator validity in this case. + assert_false(is_executing_ui_drawers_); + ui_draw_next_iterator_ = ui_drawers_.begin(); + is_executing_ui_drawers_ = true; + while (ui_draw_next_iterator_ != ui_drawers_.end()) { + // The current iterator may be invalidated, and ui_draw_next_iterator_ may + // be changed, during the execution of the drawer if the list of the drawers + // is modified by it - don't assume that after the call + // ui_draw_next_iterator_ will be the same as + // std::next(ui_draw_next_iterator_) before it. + auto it_current = ui_draw_next_iterator_++; + // Don't draw twice if already drawn in this frame (may happen if the Z + // order of a drawer was increased from below the current one to above it by + // one of the drawers). + if (it_current->second.last_draw != ui_draw_current_) { + ui_draw_current_z_order_ = it_current->first; + it_current->second.last_draw = ui_draw_current_; + it_current->second.drawer->Draw(ui_draw_context); + } + } + is_executing_ui_drawers_ = false; + ++ui_draw_current_; +} + +void Presenter::SetPaintModeFromUIThread(PaintMode new_mode) { + // Can be modified only from the UI thread, so can skip locking if it's the + // same. + if (paint_mode_ == new_mode) { + return; + } + { + std::lock_guard lock(paint_mode_mutex_); + paint_mode_ = new_mode; + } + UpdateUITicksNeededFromUIThread(); +} + +Presenter::PaintMode Presenter::GetDesiredPaintModeFromUIThread( + bool is_paintable) const { + if (!is_paintable) { + // The only case when kNone can be returned, for surface connection updates + // when it's known that the UI thread currently has access to the connection + // lifecycle. + return PaintMode::kNone; + } + if (!cvars::host_present_from_non_ui_thread) { + return PaintMode::kUIThreadOnRequest; + } + if (surface_paint_connection_has_implicit_vsync_) { + // Don't be causing host vertical sync CPU waits in the thread generating + // the guest output. + return PaintMode::kUIThreadOnRequest; + } + if (!ui_drawers_.empty()) { + // The UI can be drawn only by the UI thread, and it needs to be drawn - + // paint in the UI thread. + return PaintMode::kUIThreadOnRequest; + } + // Only the guest output needs to be drawn - let the guest output thread + // present immediately for a lower latency. + return PaintMode::kGuestOutputThreadImmediately; +} + +void Presenter::DisconnectPaintingFromSurfaceFromUIThread( + SurfacePaintConnectionState new_state) { + assert_false(IsConnectedSurfacePaintConnectionState(new_state)); + if (IsConnectedSurfacePaintConnectionState(surface_paint_connection_state_)) { + DisconnectPaintingFromSurfaceFromUIThreadImpl(); + } + surface_paint_connection_state_ = new_state; + surface_paint_connection_has_implicit_vsync_ = false; + surface_width_in_paint_connection_ = 0; + surface_height_in_paint_connection_ = 0; +} + +void Presenter::UpdateSurfacePaintConnectionFromUIThread( + bool* repaint_needed_out, bool update_paint_mode_to_desired) { + assert_not_null(surface_); + + // Validate that painting lifecycle is accessible by the UI thread currently, + // not given to the guest output thread. The mode can be modified only by + // the UI thread, so no need to lock the mutex. + assert_true(paint_mode_ != PaintMode::kGuestOutputThreadImmediately); + + // Initialize repaint_needed_out for failure cases. + if (repaint_needed_out) { + *repaint_needed_out = false; + } + + // If the connection state is kUnconnectedSurfaceReportedUnusable, the + // implementation has reported that the surface is not usable by the presenter + // at all, and it's pointless to retry connecting to it. + if (surface_paint_connection_state_ != + SurfacePaintConnectionState::kUnconnectedSurfaceReportedUnusable) { + uint32_t surface_width = 0, surface_height = 0; + bool surface_area_available = + surface_->GetSize(surface_width, surface_height); + if (!surface_area_available) { + // The surface is currently zero-area (or has become zero-area), try again + // when it's resized. + DisconnectPaintingFromSurfaceFromUIThread( + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange); + } else { + bool is_reconnect = IsConnectedSurfacePaintConnectionState( + surface_paint_connection_state_); + bool is_vsync_implicit = false; + SurfacePaintConnectResult connect_result = + ConnectOrReconnectPaintingToSurfaceFromUIThread( + *surface_, surface_width, surface_height, + surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable, + is_vsync_implicit); + switch (connect_result) { + case SurfacePaintConnectResult::kSuccess: + if (repaint_needed_out) { + *repaint_needed_out = true; + } + // Fallthrough to common success handling. + case SurfacePaintConnectResult::kSuccessUnchanged: + // Don't know yet what the first result was (success or suboptimal). + surface_paint_connection_was_optimal_at_successful_paint_ = false; + surface_paint_connection_state_ = + SurfacePaintConnectionState::kConnectedPaintable; + surface_paint_connection_has_implicit_vsync_ = is_vsync_implicit; + surface_width_in_paint_connection_ = surface_width; + surface_height_in_paint_connection_ = surface_height; + if (!is_reconnect) { + *repaint_needed_out = true; + } + break; + case SurfacePaintConnectResult::kFailure: + surface_paint_connection_state_ = + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange; + break; + case SurfacePaintConnectResult::kFailureSurfaceUnusable: + surface_paint_connection_state_ = + SurfacePaintConnectionState::kUnconnectedSurfaceReportedUnusable; + break; + } + } + } + + if (update_paint_mode_to_desired) { + SetPaintModeFromUIThread(GetDesiredPaintModeFromUIThread( + surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable)); + } +} + +bool Presenter::RequestPaintOrConnectionRecoveryViaWindow( + bool force_ui_thread_paint_tick) { + // Can be called from any thread if an existing window_ is available in it, + // and it's known to have a Surface that will be the same throughout this + // call - not doing any checks whether this request can be satisfied + // theoretically. For safety, check whether the window exists unconditionally. + assert_not_null(window_); + assert_not_null(surface_); + if (ui_thread_paint_requested_.exchange(true, std::memory_order_relaxed)) { + // Invalidation pending already, no need to do it twice. + return false; + } + if (force_ui_thread_paint_tick) { + ForceUIThreadPaintTick(); + } + window_->RequestPaint(); + return true; +} + +void Presenter::UpdateSurfaceMonitorFromUIThread( + bool old_monitor_potentially_disconnected) { + // For dropping the monitor when the window is closing and is losing its + // surface, the existence of `surface_` (which implies that `window_` exists + // too) must be the condition for a non-null monitor, not just the existence + // of `window_`. +#if XE_PLATFORM_WIN32 + HMONITOR surface_new_win32_monitor = nullptr; + if (surface_) { + HWND hwnd = static_cast(window_)->hwnd(); + // The HWND may be non-existent if the window has been closed and destroyed + // (the HWND, not the xe::ui::Window) already. + if (hwnd) { + surface_new_win32_monitor = + MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL); + } + } + if (old_monitor_potentially_disconnected || + surface_win32_monitor_ != surface_new_win32_monitor) { + surface_win32_monitor_ = surface_new_win32_monitor; + if (dxgi_ui_tick_factory_ && !dxgi_ui_tick_factory_->IsCurrent()) { + // If a monitor has been newly connected, it won't appear in the old + // factory, need to recreate it. + { + Microsoft::WRL::ComPtr old_factory_output_to_release; + { + std::scoped_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + old_factory_output_to_release = std::move(dxgi_ui_tick_output_); + } + } + dxgi_ui_tick_factory_.Reset(); + } + if (!dxgi_ui_tick_factory_) { + if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgi_ui_tick_factory_)))) { + XELOGE("Presenter: Failed to create a DXGI factory"); + } + } + Microsoft::WRL::ComPtr new_dxgi_output; + if (dxgi_ui_tick_factory_ && surface_new_win32_monitor) { + new_dxgi_output = GetDXGIOutputForMonitor(dxgi_ui_tick_factory_.Get(), + surface_new_win32_monitor); + } + // If the adapter was recreated, and the old output was released before its + // destruction, notifying is still required - the vertical blank wait thread + // might have entered the condition variable wait already as the output was + // null. + bool signal_dxgi_ui_tick_control; + { + std::unique_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + bool dxgi_output_was_null = (dxgi_ui_tick_output_ == nullptr); + dxgi_ui_tick_output_ = new_dxgi_output; + signal_dxgi_ui_tick_control = + dxgi_output_was_null && AreDXGIUITicksWaitable(dxgi_ui_tick_lock); + } + if (signal_dxgi_ui_tick_control) { + dxgi_ui_tick_control_condition_.notify_all(); + } + } +#endif // XE_PLATFORM +} + +bool Presenter::InSurfaceOnMonitorFromUIThread() const { + if (!surface_) { + return false; + } +#if XE_PLATFORM_WIN32 + return surface_win32_monitor_ != nullptr; +#else + return true; +#endif // XE_PLATFORM +} + +Presenter::PaintResult Presenter::PaintAndPresent(bool execute_ui_drawers) { + assert_false(execute_ui_drawers && !is_in_ui_thread_paint_); + assert_true(surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable); + PaintResult result = PaintAndPresentImpl(execute_ui_drawers); + switch (result) { + case PaintResult::kPresented: + surface_paint_connection_was_optimal_at_successful_paint_ = true; + break; + case PaintResult::kPresentedSuboptimal: + // Make outdated if previously optimal, now suboptimal, but don't cause + // the connection to become outdated if it has been suboptimal from the + // very beginning. + if (surface_paint_connection_was_optimal_at_successful_paint_) { + surface_paint_connection_state_ = + SurfacePaintConnectionState::kConnectedOutdated; + } + break; + case PaintResult::kNotPresentedConnectionOutdated: + surface_paint_connection_state_ = + SurfacePaintConnectionState::kConnectedOutdated; + break; + default: + // Another issue not directly related to the surface connection. + break; + } + return result; +} + +void Presenter::HandleUIDrawersChangeFromUIThread(bool drawers_were_empty) { + if (is_in_ui_thread_paint_) { + // Defer the refresh so no dangerous lifecycle-related changes happen during + // drawing. + if (!ui_drawers_.empty()) { + request_ui_paint_after_current_ui_thread_paint_ = true; + } + return; + } + + if (paint_mode_ == PaintMode::kNone) { + // Not connected, no point in refreshing (checking a more conservative + // paint_mode_ because the actual connection state may currently be owned by + // the guest output thread instead) or in toggling the ownership (the rest + // of the function can assume it's not kNone). + return; + } + + if (ui_drawers_.empty() != drawers_were_empty) { + // Require the UI thread to paint if it needs the UI, or let the guest + // output thread paint immediately if not. + SetPaintModeFromUIThread(GetDesiredPaintModeFromUIThread(true)); + // Make sure the ticks for limiting the UI frame rate are sent. + UpdateUITicksNeededFromUIThread(); + } + + // Request painting so the changes to the UI drawer list are reflected as + // quickly as possible. + // RequestUIPaintFromUIThread is not enough, because a paint request is also + // needed if disabling the UI, to force paint a frame without the UI as soon + // as possible - it can't be dropped if ui_drawers_ is empty. + // The coarse painting availability (and thus the availability of `window_`, + // which is required for the paint mode to be anything else than kNone) has + // already been checked above. + ForceUIThreadPaintTick(); + window_->RequestPaint(); +} + +void Presenter::UpdateUITicksNeededFromUIThread() { +#if XE_PLATFORM_WIN32 + bool new_needed = AreUITicksNeededFromUIThread(); + if (dxgi_ui_ticks_needed_ == new_needed) { + return; + } + bool signal_dxgi_ui_tick_control; + { + std::unique_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + dxgi_ui_ticks_needed_ = new_needed; + signal_dxgi_ui_tick_control = AreDXGIUITicksWaitable(dxgi_ui_tick_lock); + } + if (signal_dxgi_ui_tick_control) { + dxgi_ui_tick_control_condition_.notify_all(); + } +#endif +} + +void Presenter::WaitForUITickFromUIThread() { +#if XE_PLATFORM_WIN32 + if (!AreUITicksNeededFromUIThread()) { + return; + } + std::unique_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + uint64_t last_vblank_before_wait = dxgi_ui_tick_last_vblank_; + while (true) { + // Guest output present requests should interrupt the wait as quickly as + // possible as they should be fulfilled as early as possible. + if (dxgi_ui_tick_force_requested_) { + dxgi_ui_tick_force_requested_ = false; + return; + } + if (!AreDXGIUITicksWaitable(dxgi_ui_tick_lock)) { + return; + } + if (dxgi_ui_tick_last_vblank_ > dxgi_ui_tick_last_draw_) { + // If there have been multiple vblanks during the wait for some reason, + // next time draw the UI immediately. + dxgi_ui_tick_last_draw_ = std::min(last_vblank_before_wait + uint64_t(1), + dxgi_ui_tick_last_vblank_); + return; + } + dxgi_ui_tick_signal_condition_.wait(dxgi_ui_tick_lock); + } +#endif // XE_PLATFORM +} + +void Presenter::ForceUIThreadPaintTick() { +#if XE_PLATFORM_WIN32 + std::scoped_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + dxgi_ui_tick_force_requested_ = true; +#endif // XE_PLATFORM +} + +#if XE_PLATFORM_WIN32 +Microsoft::WRL::ComPtr Presenter::GetDXGIOutputForMonitor( + IDXGIFactory1* factory, HMONITOR monitor) { + Microsoft::WRL::ComPtr adapter; + for (UINT adapter_index = 0; SUCCEEDED(factory->EnumAdapters( + adapter_index, adapter.ReleaseAndGetAddressOf())); + ++adapter_index) { + Microsoft::WRL::ComPtr output; + for (UINT output_index = 0; + SUCCEEDED(adapter->EnumOutputs(output_index, &output)); + ++output_index) { + DXGI_OUTPUT_DESC output_desc; + if (SUCCEEDED(output->GetDesc(&output_desc)) && + output_desc.Monitor == monitor) { + return std::move(output); + } + } + } + return nullptr; +} + +void Presenter::DXGIUITickThread() { + std::unique_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + while (true) { + if (dxgi_ui_tick_thread_shutdown_) { + return; + } + if (!AreDXGIUITicksWaitable(dxgi_ui_tick_lock)) { + dxgi_ui_tick_control_condition_.wait(dxgi_ui_tick_lock); + continue; + } + // Wait for vertical blank, with the mutex unlocked (holding a new reference + // to the current output while it's happening) so subscribers can still do + // early-out checks. + bool wait_succeeded; + { + Microsoft::WRL::ComPtr dxgi_output = dxgi_ui_tick_output_; + dxgi_ui_tick_lock.unlock(); + wait_succeeded = SUCCEEDED(dxgi_ui_tick_output_->WaitForVBlank()); + } + dxgi_ui_tick_lock.lock(); + if (wait_succeeded) { + ++dxgi_ui_tick_last_vblank_; + } else { + // Lost the ability to wait for a vertical blank on this output, notify + // the waiting threads, and wait for a new one. + dxgi_ui_tick_output_.Reset(); + } + dxgi_ui_tick_signal_condition_.notify_all(); + } +} +#endif // XE_PLATFORM + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/presenter.h b/src/xenia/ui/presenter.h new file mode 100644 index 000000000..5ead8cb90 --- /dev/null +++ b/src/xenia/ui/presenter.h @@ -0,0 +1,1034 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_PRESENTER_H_ +#define XENIA_UI_PRESENTER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/byte_order.h" +#include "xenia/base/cvar.h" +#include "xenia/base/math.h" +#include "xenia/base/platform.h" +#include "xenia/ui/surface.h" +#include "xenia/ui/ui_drawer.h" + +#if XE_PLATFORM_WIN32 +// Must be included before DXGI for things like NOMINMAX, and also needed for +// Windows handle types. +#include "xenia/base/platform_win.h" + +#include +#include +#endif // XE_PLATFORM + +// For implementation use. +DECLARE_bool(present_render_pass_clear); + +namespace xe { +namespace ui { + +class Presenter; +class Window; +class Win32Window; + +class UIDrawContext { + public: + UIDrawContext(const UIDrawContext& context) = delete; + UIDrawContext& operator=(const UIDrawContext& context) = delete; + virtual ~UIDrawContext() = default; + + Presenter& presenter() const { return presenter_; } + + // It's assumed that the render target size will be either equal to the size + // of the surface, or the render target will be stretched to cover the entire + // surface (not in the corner of the surface). + uint32_t render_target_width() const { return render_target_width_; } + uint32_t render_target_height() const { return render_target_height_; } + + protected: + explicit UIDrawContext(Presenter& presenter, uint32_t render_target_width, + uint32_t render_target_height) + : presenter_(presenter), + render_target_width_(render_target_width), + render_target_height_(render_target_height) {} + + private: + Presenter& presenter_; + uint32_t render_target_width_; + uint32_t render_target_height_; +}; + +struct RawImage { + uint32_t width = 0; + uint32_t height = 0; + size_t stride = 0; + // R8 G8 B8 X8. The last row is not required to be padded to the stride. + std::vector data; +}; + +// The presenter displays up to two layers of content on a host surface: +// - Guest output image, focusing on lowering latency and maintaining stable +// frame pacing, with various scaling and sharpening methods and letterboxing; +// - Xenia's internal UI (such as the profiler and Dear ImGui). +// +// The guest output image may be refreshed from any thread generating it +// (usually the GPU emulation thread), as long as there are no multiple threads +// doing that simultaneously (since that would functionally be a race condition +// even if refreshing is performed in a critical section). +// +// The UI overlays are managed entirely by the UI thread. +// +// Painting on the host surface may occur in two places: +// - If there are no UI overlays, painting of the guest output may be performed +// immediately from the thread refreshing it, to bypass the OS scheduling and +// event handling. This is especially important on platforms where the native +// surface paint event has a frame rate limit (such as the display refresh +// rate), and the limit may differ greatly from the guest frame rate (such as +// presenting a 30 or 60 FPS guest to a 144 Hz host surface). +// - If the UI overlays (owned by the UI thread) are present, painting of both +// the guest output (is available) and the UI is done exclusively from the +// platform paint event handler. The guest output without UI overlays may also +// be painted from the platform paint callback in certain cases, such as when +// an additional paint beyond the guest's frame rate may be needed (like when +// resizing the window), or when painting from the thread refreshing the guest +// output is undesirable (for instance, if it will result in waiting for host +// vertical sync in that thread too early if host vertical sync can't be +// disabled on the platform, blocking the next frame of GPU emulation). +// +// The composition of the guest and the UI is done by Xenia manually, as opposed +// to using platform functionality such as DirectComposition, in order to have +// more predictability of GPU queue scheduling, but primarily to be able to take +// advantage of independent host presentation where it's available, so variable +// refresh rate may be used where possible, and latency may be significantly +// reduced. Also, at least on some configurations (checked on Windows 11 21H2 on +// Nvidia GeForce GTX 1070 with driver version 472.12), when in borderless +// fullscreen, any composition causes the DXGI Present to wait for vertical sync +// on the GPU even if the sync interval 0 is specified. +// +// An intermediate image with the size requested by the guest is used for guest +// output in all cases. Even though it adds some GPU overhead, especially in the +// 1:1 size case, using it solves multiple issues: +// - Presentation may be done more often than by the guest. +// - There is clear separation between pre-scaling and mid- / post-scaling +// operations. The gamma ramp, for instance, may be applied before scaling, +// with one lookup per pixel rather than four with fetch4. +// - A simpler compute shader may be used instead of setting up the whole +// graphics pipeline for copying in the GPU command processor in all cases, +// while Direct3D 12 does not allow UAVs for swap chain buffers. +// +// The presenter limits the frame rate of the UI overlay (when possible) to a +// value that's ideally the refresh rate of the monitor containing the window if +// the platform's paint event doesn't have an internal limiter. However, where +// possible, the arrival of a new guest output image will interrupt the UI tick +// wait. +// +// Because the UI overlays preclude the possibility of presenting directly from +// the thread refreshing the guest output, and on some platforms, result in the +// frame rate limiting of paint events manifesting itself, there must be no +// persistent UI overlays that haven't been explicitly requested by the user. +// However, for temporary (primarily non-modal) UI elements such as various +// timed notifications, using the Presenter should be preferred to implementing +// them via overlaying native windows on top of the presentation surface on +// platforms where the concept of independent presentation exists, as multiple +// windows will result in native composition disabling it. +// +// The painting connection between the Presenter and the Surface can be managed +// only by the UI thread. However, the thread refreshing the guest output may +// still mark the current connection as outdated and ask the UI thread (by +// requesting painting) to try to recover - but the guest output refresh thread +// must not try to reconnect by itself, as methods of the Surface are available +// only to the UI thread. +class Presenter { + public: + // May be actually called on the UI thread even if statically_from_ui_thread + // is false, such as when the guest output is refreshed by the UI thread. + using HostGpuLossCallback = + std::function; + static void FatalErrorHostGpuLossCallback(bool is_responsible, + bool statically_from_ui_thread); + + class GuestOutputRefreshContext { + public: + GuestOutputRefreshContext(const GuestOutputRefreshContext& context) = + delete; + GuestOutputRefreshContext& operator=( + const GuestOutputRefreshContext& context) = delete; + virtual ~GuestOutputRefreshContext() = default; + + // Sets whether the source actually has no more than 8 bits of precision + // (though the image provided by the refresher may still have a higher + // storage precision). If never called, assuming it's false. + void SetIs8bpc(bool is_8bpc) { is_8bpc_out_ref_ = is_8bpc; } + + protected: + GuestOutputRefreshContext(bool& is_8bpc_out_ref) + : is_8bpc_out_ref_(is_8bpc_out_ref) { + is_8bpc_out_ref = false; + } + + private: + bool& is_8bpc_out_ref_; + }; + + class GuestOutputPaintConfig { + public: + enum class Effect { + kBilinear, + kCas, + // AMD FidelityFX Super Resolution upsampling, Contrast Adaptive + // Sharpening otherwise. + kFsr, + }; + + // This value is used as a lerp factor. + static constexpr float kCasAdditionalSharpnessMin = 0.0f; + static constexpr float kCasAdditionalSharpnessMax = 1.0f; + static constexpr float kCasAdditionalSharpnessDefault = 0.0f; + static_assert(kCasAdditionalSharpnessDefault >= + kCasAdditionalSharpnessMin && + kCasAdditionalSharpnessDefault <= kCasAdditionalSharpnessMax); + + // EASU (as well as CAS) is designed for scaling by factors of up to 2x2. + // Some sensible limit for unusual cases, when the game for some reason + // presents a very small back buffer. + // This is enough for 480p > 960p > 1920p > 3840p > 7680p (bigger than 8K, + // or 4320p). + static constexpr uint32_t kFsrMaxUpscalingPassesMax = 4; + + static constexpr float kFsrSharpnessReductionMin = 0.0f; + // "Values above 2.0 won't make a visible difference." + // https://raw.githubusercontent.com/GPUOpen-Effects/FidelityFX-FSR/master/docs/FidelityFX-FSR-Overview-Integration.pdf + static constexpr float kFsrSharpnessReductionMax = 2.0f; + static constexpr float kFsrSharpnessReductionDefault = 0.2f; + static_assert(kFsrSharpnessReductionDefault >= kFsrSharpnessReductionMin && + kFsrSharpnessReductionDefault <= kFsrSharpnessReductionMax); + + // In the sharpness setters, min / max with a constant as the first argument + // also drops NaNs. + + Effect GetEffect() const { return effect_; } + void SetEffect(Effect new_effect) { effect_ = new_effect; } + + float GetCasAdditionalSharpness() const { + return cas_additional_sharpness_; + } + void SetCasAdditionalSharpness(float new_cas_additional_sharpness) { + cas_additional_sharpness_ = std::min( + kCasAdditionalSharpnessMax, + std::max(kCasAdditionalSharpnessMin, new_cas_additional_sharpness)); + } + + uint32_t GetFsrMaxUpsamplingPasses() const { + return fsr_max_upsampling_passes_; + } + void SetFsrMaxUpsamplingPasses(uint32_t new_fsr_max_upsampling_passes) { + fsr_max_upsampling_passes_ = + std::min(kFsrMaxUpscalingPassesMax, + std::max(uint32_t(1), new_fsr_max_upsampling_passes)); + } + + // In stops. + float GetFsrSharpnessReduction() const { return fsr_sharpness_reduction_; } + void SetFsrSharpnessReduction(float new_fsr_sharpness_reduction) { + fsr_sharpness_reduction_ = std::min( + kFsrSharpnessReductionMax, + std::max(kFsrSharpnessReductionMin, new_fsr_sharpness_reduction)); + } + + // Very tiny effect, but highly noticeable, for instance, on the sky in the + // 4D5307E6 main menu (prominently in Custom Games, especially with FSR - + // banding around the clouds can be clearly seen without dithering with 8bpc + // final host output). + bool GetDither() const { return dither_; } + void SetDither(bool new_dither) { dither_ = new_dither; } + + private: + // Tools, rather than the emulator itself, must use kBilinear as the image + // must be as close to the original front buffer as possible. + Effect effect_ = Effect::kBilinear; + float cas_additional_sharpness_ = kCasAdditionalSharpnessDefault; + uint32_t fsr_max_upsampling_passes_ = kFsrMaxUpscalingPassesMax; + float fsr_sharpness_reduction_ = kFsrSharpnessReductionDefault; + bool dither_ = false; + }; + + Presenter(const Presenter& presenter) = delete; + Presenter& operator=(const Presenter& presenter) = delete; + virtual ~Presenter(); + + virtual Surface::TypeFlags GetSupportedSurfaceTypes() const = 0; + + // For calling from the Window for the Presenter attached to it. + // May be called from the destructor of the presenter through the window. + void SetWindowSurfaceFromUIThread(Window* new_window, Surface* new_surface); + void OnSurfaceMonitorUpdateFromUIThread( + bool old_monitor_potentially_disconnected); + void OnSurfaceResizeFromUIThread(); + + // For calling from the platform paint event handler. Refreshes the surface + // connection if needed, and also paints if possible and if needed (if there + // are no UI overlays, and the guest output is presented directly from the + // thread refreshing it, the paint may be skipped unless there has been an + // explicit request previously or force_paint is true). If painting happens, + // both the guest output and the UI overlays (if any are active) are drawn. + // The background / letterbox of the painted context will be black - windows + // should preferably have a black background before a Presenter is attached to + // them too. + void PaintFromUIThread(bool force_paint = false); + + // Pass 0 as width or height to disable guest output until the next refresh + // with an actual size. The callback will receive a backend-specific context, + // and will not be called in case of an error such as the wrong size, or if + // guest output is disabled. Returns whether the callback was called and it + // returned true. The callback must submit all updating work to the host GPU + // before successfully returning, and also signal all the GPU synchronization + // primitives required by the GuestOutputRefreshContext implementation. + bool RefreshGuestOutput( + uint32_t frontbuffer_width, uint32_t frontbuffer_height, + uint32_t screen_width, uint32_t screen_height, + std::function refresher); + // The implementation must be callable from any thread, including from + // multiple at the same time, and it should acquire the latest guest output + // image via ConsumeGuestOutput. + virtual bool CaptureGuestOutput(RawImage& image_out) = 0; + const GuestOutputPaintConfig& GetGuestOutputPaintConfigFromUIThread() const { + return guest_output_paint_config_; + } + // For simplicity, may be called repeatedly even if no changes have been made. + void SetGuestOutputPaintConfigFromUIThread( + const GuestOutputPaintConfig& new_config); + + void AddUIDrawerFromUIThread(UIDrawer* drawer, size_t z_order); + void RemoveUIDrawerFromUIThread(UIDrawer* drawer); + + // Requests (re)painting with the UI if there's UI to draw. + void RequestUIPaintFromUIThread(); + + protected: + enum class PaintResult { + kPresented, + kPresentedSuboptimal, + // Refused for internal reasons or a host API side failure, but still may + // try to present without resetting the graphics provider in the future. + kNotPresented, + kNotPresentedConnectionOutdated, + kGpuLostExternally, + kGpuLostResponsible, + }; + + enum class SurfacePaintConnectResult { + // Redrawing not necessary, nothing changed. Must not be returned for a new + // connection (when was previously disconnected from the surface). + kSuccessUnchanged, + kSuccess, + kFailure, + kFailureSurfaceUnusable, + }; + + static constexpr uint32_t kGuestOutputMailboxSize = 3; + + struct GuestOutputProperties { + // At least any value being 0 here means the guest output is disabled for + // this frame. + uint32_t frontbuffer_width; + uint32_t frontbuffer_height; + // Guest screen size (primarily for the target aspect ratio, which may be + // different than that of the frontbuffer). + uint32_t screen_width; + uint32_t screen_height; + bool is_8bpc; + + GuestOutputProperties() { SetToInactive(); } + + bool IsActive() const { + return frontbuffer_width && frontbuffer_height && screen_width && + screen_height; + } + + void SetToInactive() { + frontbuffer_width = 0; + frontbuffer_height = 0; + screen_width = 0; + screen_height = 0; + is_8bpc = false; + } + }; + + enum class GuestOutputPaintEffect { + kBilinear, + kBilinearDither, + kCasSharpen, + kCasSharpenDither, + kCasResample, + kCasResampleDither, + kFsrEasu, + kFsrRcas, + kFsrRcasDither, + + kCount, + }; + + static constexpr bool CanGuestOutputPaintEffectBeIntermediate( + GuestOutputPaintEffect effect) { + switch (effect) { + case GuestOutputPaintEffect::kBilinear: + // Dithering is never performed in intermediate passes because it may be + // interpreted as features by the subsequent passes. + case GuestOutputPaintEffect::kBilinearDither: + case GuestOutputPaintEffect::kCasSharpenDither: + case GuestOutputPaintEffect::kCasResampleDither: + case GuestOutputPaintEffect::kFsrRcasDither: + return false; + default: + // The result of any other effect can be stretched with bilinear + // filtering to the final resolution. + return true; + }; + } + + static constexpr bool CanGuestOutputPaintEffectBeFinal( + GuestOutputPaintEffect effect) { + switch (effect) { + case GuestOutputPaintEffect::kFsrEasu: + return false; + default: + return true; + }; + } + + // The longest path is kFsrMaxUpscalingPassesMax + optionally RCAS + + // optionally bilinear, when upscaling by more than + // 2^kFsrMaxUpscalingPassesMax along any direction. + // Non-FSR paths are either only bilinear, only CAS, or (when upscaling by + // more than 2 along any direction) CAS followed by bilinear. + static constexpr size_t kMaxGuestOutputPaintEffects = + GuestOutputPaintConfig::kFsrMaxUpscalingPassesMax + 2; + + struct GuestOutputPaintFlow { + // Letterbox on up to 4 sides. + static constexpr size_t kMaxClearRectangles = 4; + + struct ClearRectangle { + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + }; + + GuestOutputProperties properties; + + // If 0, don't display the guest output. + size_t effect_count; + std::array effects; + std::array, kMaxGuestOutputPaintEffects> + effect_output_sizes; + + // Offset of the rectangle for final drawing to the host window with + // letterboxing. + int32_t output_x; + int32_t output_y; + + // If there is guest output (effect_count is not 0), contains the letterbox + // rectangles around the guest output. + size_t letterbox_clear_rectangle_count; + std::array letterbox_clear_rectangles; + + void GetEffectInputSize(size_t effect_index, uint32_t& width_out, + uint32_t& height_out) const { + assert_true(effect_index < effect_count); + if (!effect_index) { + width_out = properties.frontbuffer_width; + height_out = properties.frontbuffer_height; + return; + } + const std::pair& intermediate_size = + effect_output_sizes[effect_index - 1]; + width_out = intermediate_size.first; + height_out = intermediate_size.second; + } + + void GetEffectOutputOffset(size_t effect_index, int32_t& x_out, + int32_t& y_out) const { + assert_true(effect_index < effect_count); + if (effect_index + 1 < effect_count) { + x_out = 0; + y_out = 0; + return; + } + x_out = output_x; + y_out = output_y; + } + }; + + struct BilinearConstants { + int32_t output_offset[2]; + float output_size_inv[2]; + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index) { + flow.GetEffectOutputOffset(effect_index, output_offset[0], + output_offset[1]); + const std::pair& output_size = + flow.effect_output_sizes[effect_index]; + output_size_inv[0] = 1.0f / float(output_size.first); + output_size_inv[1] = 1.0f / float(output_size.second); + } + }; + + static constexpr float CalculateCasPostSetupSharpness(float sharpness) { + // CasSetup const1.x. + return -1.0f / (8.0f - 3.0f * sharpness); + } + + struct CasSharpenConstants { + int32_t output_offset[2]; + float sharpness_post_setup; + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index, + const GuestOutputPaintConfig& config) { + flow.GetEffectOutputOffset(effect_index, output_offset[0], + output_offset[1]); + sharpness_post_setup = + CalculateCasPostSetupSharpness(config.GetCasAdditionalSharpness()); + } + }; + + struct CasResampleConstants { + int32_t output_offset[2]; + // Input size / output size. + float input_output_size_ratio[2]; + float sharpness_post_setup; + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index, + const GuestOutputPaintConfig& config) { + flow.GetEffectOutputOffset(effect_index, output_offset[0], + output_offset[1]); + uint32_t input_width, input_height; + flow.GetEffectInputSize(effect_index, input_width, input_height); + const std::pair& output_size = + flow.effect_output_sizes[effect_index]; + input_output_size_ratio[0] = + float(input_width) / float(output_size.first); + input_output_size_ratio[1] = + float(input_height) / float(output_size.second); + sharpness_post_setup = + CalculateCasPostSetupSharpness(config.GetCasAdditionalSharpness()); + } + }; + + struct FsrEasuConstants { + // No output offset because the EASU pass is always done to an intermediate + // framebuffer. + float input_output_size_ratio[2]; + float input_size_inv[2]; + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index) { + uint32_t input_width, input_height; + flow.GetEffectInputSize(effect_index, input_width, input_height); + const std::pair& output_size = + flow.effect_output_sizes[effect_index]; + input_output_size_ratio[0] = + float(input_width) / float(output_size.first); + input_output_size_ratio[1] = + float(input_height) / float(output_size.second); + input_size_inv[0] = 1.0f / float(input_width); + input_size_inv[1] = 1.0f / float(input_height); + } + }; + + struct FsrRcasConstants { + int32_t output_offset[2]; + float sharpness_post_setup; + + static float CalculatePostSetupSharpness(float sharpness_reduction_stops) { + // FsrRcasCon const0.x. + return std::exp2f(-sharpness_reduction_stops); + } + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index, + const GuestOutputPaintConfig& config) { + flow.GetEffectOutputOffset(effect_index, output_offset[0], + output_offset[1]); + sharpness_post_setup = + CalculatePostSetupSharpness(config.GetFsrSharpnessReduction()); + } + }; + + explicit Presenter(HostGpuLossCallback host_gpu_loss_callback) + : host_gpu_loss_callback_(host_gpu_loss_callback) {} + + // Must be called by the implementation's initialization, before the presenter + // is used for anything. + bool InitializeCommonSurfaceIndependent(); + + // ConnectOrReconnect and Disconnect are callable only by the UI thread and + // only when it has access to painting (PaintMode is not + // kGuestOutputThreadImmediately). + // Called only for a non-zero-area surface potentially supporting painting via + // the presenter. In case of a failure, internally no resources referencing + // the surface must be held by the implementation anymore - the implementation + // must be left in the same state as after + // DisconnectPaintingFromSurfaceFromUIThreadImpl. If the call is successful, + // the implementation must write to is_vsync_implicit_out whether the + // connection will now have vertical sync forced by the host window system, + // which may cause undesirable waits on the CPU when beginning or ending + // frames. + virtual SurfacePaintConnectResult + ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) = 0; + // Releases resources referencing the surface in the implementation if they + // are held by it. Call through DisconnectPaintingFromSurfaceFromUIThread to + // ensure the implementation is only called while the connection is active. + virtual void DisconnectPaintingFromSurfaceFromUIThreadImpl() = 0; + + // The returned lock interlocks multiple consumers (but not the producer and + // the consumer) and must be held while accessing implementation-specific + // objects that depend on the image or its index in the mailbox (unless there + // are other locking mechanisms involved for the resources, such as reference + // counting for the guest output images, which doesn't have to be atomic + // though for the reason described later in this paragraph, or assumptions + // like of main target painting being possible only in at most one thread at + // once). While this lock is held, the currently acquired image index can't be + // changed (by other consumers advancing the acquired image index to the new + // ready image index), so the image with the index given by this function + // can't be released and be made writable or given to a different consumer + // (thus it's owned exclusively by the consumer who has called this function). + // The properties are returned by copy rather than returning a pointer to them + // or asking the consumer to pull them for the current mailbox index, so there + // are less things to take into consideration while leaving the guest output + // consumer critical section earlier (as if a pointer was returned, the data + // behind it could be overwritten at any time after leaving the consumer + // critical section) if the implementation has its own synchronization + // mechanisms that allow for doing so as described earlier. Returns UINT32_MAX + // as the mailbox index if the image is inactive (if it's active, it has + // proper properties though). + [[nodiscard]] std::unique_lock ConsumeGuestOutput( + uint32_t& mailbox_index_or_max_if_inactive_out, + GuestOutputProperties* properties_out, + GuestOutputPaintConfig* paint_config_out); + // The properties are passed explicitly, not taken from the current acquired + // image, so it can be called for a copy of the acquired image's properties + // outside the consumer lock if the implementation has its own synchronization + // (like reference counting for the guest output images) that makes it + // possible to leave the consumer critical section earlier. Also, the guest + // output paint configuration is passed explicitly too so calling this + // function multiple times is safer. + GuestOutputPaintFlow GetGuestOutputPaintFlow( + const GuestOutputProperties& properties, uint32_t host_rt_width, + uint32_t host_rt_height, uint32_t max_rt_width, uint32_t max_rt_height, + const GuestOutputPaintConfig& config) const; + // is_8bpc_out_ref is where to write whether the source actually has no more + // than 8 bits of precision per channel (though the image provided by the + // refresher may still have a higher storage precision) - if not written, it + // will be assumed to be false. + virtual bool RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out_ref) = 0; + + // For guest output capturing (for debugging use thus - shouldn't be adding + // any noise like dithering that's not present in the original image), + // converting a 10bpc RGB pixel to 8bpc that can be stored in common image + // formats. + static uint32_t Packed10bpcRGBTo8bpcBytes(uint32_t rgb10) { + // Conversion almost according to the Direct3D 10+ rules (unorm > float > + // unorm), but with one multiplication rather than separate division and + // multiplication - the results are the same for unorm10 to unorm8. + if constexpr (std::endian::native == std::endian::big) { + return (uint32_t(float(rgb10 & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 24) | + (uint32_t(float((rgb10 >> 10) & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 16) | + (uint32_t(float((rgb10 >> 20) & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 8) | + uint32_t(0xFF); + } + return uint32_t(float(rgb10 & 0x3FF) * (255.0f / 1023.0f) + 0.5f) | + (uint32_t(float((rgb10 >> 10) & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 8) | + (uint32_t(float((rgb10 >> 20) & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 16) | + (uint32_t(0xFF) << 24); + } + + // Paints and presents the guest output if available (or just solid black + // color), and if requested, the UI on top of it. + // + // May be called from the non-UI thread, but only to paint the guest output + // (no UI drawing, with execute_ui_drawers disabled). + // + // Call via PaintAndPresent. + virtual PaintResult PaintAndPresentImpl(bool execute_ui_drawers) = 0; + + // For calling from the painting implementations if requested. + void ExecuteUIDrawersFromUIThread(UIDrawContext& ui_draw_context); + + private: + enum class PaintMode { + // Don't paint at all. + // Painting lifecycle is accessible only by the UI thread. + // window_->RequestPaint() must not be called in this mode at all regardless + // of whether the Window object exists because the Window object in this + // case may correspond to a window without a paintable Surface (in a closed + // state, or in the middle of a surface change), and non-UI threads (such as + // the guest output thread) may result in a race condition internally inside + // Window::RequestPaint during the access to the Window's state, such as the + // availability of the Surface that can handle the paint (therefore, if + // there's no Surface, this is the only valid mode). + kNone, + // Guest output refreshing notifies the `window_`, which must be valid and + // safe to call RequestPaint for, that painting should be done in the UI + // thread (including the UI if needed). Painting is possible, and painting + // lifecycle is accessible, only by the UI thread. + kUIThreadOnRequest, + // Paint immediately in the guest output thread for lower latency. The + // `window_`, however, may be notified that the surface painting connection + // has become outdated (via RequestPaint, as in this case the UI thread will + // need to repaint as sooner as possible after reconnecting anyway), and + // change the surface connection state accordingly (only to + // kConnectedOutdated). + // Painting is possible only by the guest output thread, lifecycle + // management cannot be done from the UI thread until it takes over. + kGuestOutputThreadImmediately, + }; + + enum class SurfacePaintConnectionState { + // No surface at all, or couldn't connect with the current state of the + // surface (such as because the surface was zero-sized because the window + // was minimized, for example). Or, the connection has become outdated, and + // the attempt to reconnect at kRetryConnectingSoon has failed. Try to + // reconnect if anything changes in the state of the surface, such as its + // size. + kUnconnectedRetryAtStateChange, + // Can't connect to the current existing surface (the surface has been lost + // or it's completely incompatible). No point in retrying connecting until + // the surface is replaced. + kUnconnectedSurfaceReportedUnusable, + // Everything is fine, can paint. The connection might have become + // suboptimal though, and haven't tried refreshing yet, but still usable for + // painting nonetheless. + kConnectedPaintable, + // The implementation still holds resources associated with the connection, + // but presentation has reported that it has become outdated, try + // reconnecting as soon as possible (at the next paint attempt, requesting + // it if needed). This is the only state that the guest output thread may + // transition the connection to (from kConnectedPaintable only) if it has + // access to painting (the paint mode is kGuestOutputThreadImmediately). + kConnectedOutdated, + }; + + static constexpr bool IsConnectedSurfacePaintConnectionState( + SurfacePaintConnectionState connection_state) { + return connection_state == + SurfacePaintConnectionState::kConnectedPaintable || + connection_state == SurfacePaintConnectionState::kConnectedOutdated; + } + + struct UIDrawerReference { + UIDrawer* drawer; + uint64_t last_draw; + + explicit UIDrawerReference(UIDrawer* drawer, + uint64_t last_draw = UINT64_MAX) + : drawer(drawer), last_draw(last_draw) {} + }; + + void SetPaintModeFromUIThread(PaintMode new_mode); + // Based on conditions like whether UI needs to be drawn and whether vertical + // sync is implicit - see the implementation for the requirements. + // is_paintable is an explicit parameter because this function may be called + // in two scenarios: + // - After connection updates - painting connection is owned by the UI thread, + // so the actual state can be obtained and passed here so kNone can be + // returned. + // - When merely toggling something local to the UI thread - only to toggle + // between the two threads, but not to switch from or to kNone (make sure + // it's not kNone before calling), pass `true` in this case. + PaintMode GetDesiredPaintModeFromUIThread(bool is_paintable) const; + + // Callable only by the UI thread and only when it has access to painting + // (PaintMode is not kGuestOutputThreadImmediately). + // This can be called to a surface after having not been connected to any (in + // this case, surface_paint_connection_state_ must be + // kUnconnectedRetryAtStateChange, not kUnconnectedNoUsableSurface, otherwise + // the call will be dropped), or to handle surface state changes such as + // resizing. However, this must not be called to change directly from one + // surface to another - need to disconnect prior to that, because the + // implementation may assume that the surface is still the same, and may try + // to, for instance, resize the buffers for the existing surface. + void UpdateSurfacePaintConnectionFromUIThread( + bool* repaint_needed_out, bool update_paint_mode_to_desired); + // Callable only by the UI thread and only when it has access to painting + // (PaintMode is not kGuestOutputThreadImmediately). + // See DisconnectPaintingFromSurfaceFromUIThreadImpl for more information. + void DisconnectPaintingFromSurfaceFromUIThread( + SurfacePaintConnectionState new_state); + + // Can be called from any thread if an existing window_ safe to RequestPaint + // (not closed) is available in it, so doesn't check the surface painting + // connection state. Returns whether the window_->RequestPaint() call has been + // made. + bool RequestPaintOrConnectionRecoveryViaWindow( + bool force_ui_thread_paint_tick); + + // Platform-specific function refreshing the monitor the current window + // surface is on, through the Surface or its Window. A reference to the + // monitor is held only when a Surface is available, so it's automatically + // dropped when the Window loses its Surface when it's being closed (but the + // Window object keeps being attached to the Presenter), for instance. + void UpdateSurfaceMonitorFromUIThread( + bool old_monitor_potentially_disconnected); + // Platform-specific function returning whether the surface the presenter is + // currently attached it is actually visible on any monitor. UI thread + // painting may be dropped if this returns false - need to request painting if + // the surface appears on a monitor again. May be using the state cached at + // window / surface state changes, not the actual state from the platform. + bool InSurfaceOnMonitorFromUIThread() const; + + // Calls PaintAndPresentImpl and does post-paint checks that are safe to do on + // both the UI thread and the guest output thread. See the information about + // PaintAndPresentImpl for details. + // A kPresentedSuboptimal result is returned as is, but the connection may or + // may not be made outdated if that happens - though if it's + // kPresentedSuboptimal rather than kNotPresentedConnectionOutdated, the image + // has been successfully sent to the OS presentation at least. + PaintResult PaintAndPresent(bool execute_ui_drawers); + + void HandleUIDrawersChangeFromUIThread(bool drawers_were_empty); + + bool AreUITicksNeededFromUIThread() const { + // UI drawing should be done, and painting needs to be possible (coarsely + // checking because the actual connection state, including outdated, may be + // currently unavailable from the UI thread). + // There's no need to limit the frame rate manually if there is vertical + // sync in the presentation already as that might result in inconsistent + // frame pacing and potentially skipped vertical sync intervals. + return !ui_drawers_.empty() && paint_mode_ != PaintMode::kNone && + !surface_paint_connection_has_implicit_vsync_; + } + void UpdateUITicksNeededFromUIThread(); + void WaitForUITickFromUIThread(); + // May be called from any thread. + void ForceUIThreadPaintTick(); + + // Must be called only in the end of entry points - reinitialization of the + // presenter may be done by the handler if it was called from the UI thread + // (even if the UI thread argument is false - such as when the guest output is + // refreshed on the UI thread). + HostGpuLossCallback host_gpu_loss_callback_; + + // May be accessed by the guest output thread if the paint mode is not kNone, + // to request painting (for kUIThreadOnRequest) or reconnection (for + // kGuestOutputThreadImmediately) in the UI thread. Set the paint mode to + // kNone before modifying (that naturally has to be done anyway by + // disconnecting painting). + Window* window_ = nullptr; + + // The surface of the `window_` the presenter is currently attached to. + Surface* surface_ = nullptr; + + // Mutex protecting paint_mode_ (and, in the guest output thread, objects + // related to painting themselves). + // + // The UI thread (as the mode is modifiable only by it) can use it as + // "barriers", like: + // 1) If needed, lock and disable guest output thread access to painting. + // 2) Interact with the painting connection. + // 3) If needed, lock and re-enable guest output thread access to the + // painting. + // + // On the other hand, the guest output thread _must_ hold it all the time it's + // painting, to ensure the mode stays the same while it's painting. + std::mutex paint_mode_mutex_; + // UI thread: writable, guest output thread: read-only. + PaintMode paint_mode_ = PaintMode::kNone; + + // These fields can be accessed _exclusively_ by either the UI thread or the + // guest output thread, depending on paint_mode_. + // If it's kGuestOutputThreadImmediately, they can be accessed _only_ by the + // guest output thread (though the UI thread can still read, but not modify, + // fields that are writable by the UI thread and readadable by both). + // Otherwise, they can be accessed _only_ by the UI thread. + // The connection state may be changed from the guest output thread, but only + // from kConnectedPaintable to kConnectedOutdated. + SurfacePaintConnectionState surface_paint_connection_state_ = + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange; + // If the surface connection was optimal at the last paint attempt, but now + // has become suboptimal, need to try to reconnect. But only in this case - if + // the connection has been suboptimal from the very beginning don't try to + // reconnect every frame. + bool surface_paint_connection_was_optimal_at_successful_paint_ = false; + + // Modifiable only by the UI thread (therefore can be accessed by the UI + // thread regardless of the paint mode) while (re)connecting painting to the + // surface. + bool surface_paint_connection_has_implicit_vsync_ = false; + // Modifiable only by the UI thread, can be read by the thread that's + // painting. + uint32_t surface_width_in_paint_connection_ = 0; + uint32_t surface_height_in_paint_connection_ = 0; + + // Can be set by both the UI thread and the guest output thread before doing + // window_->RequestPaint() - whether an extra painting (preceded by + // reconnection if needed, and painting) was requested, primarily after some + // state change that may effect the surface painting connection, resulting in + // the need to refresh it as soon as possible. + // + // Relaxed memory order is enough, everything that may influence painting is + // either local to the UI thread or protected with barriers elsewhere. + // + // There's no need to bother about resetting this variable when losing + // connection as the next successful reconnection should be followed by a + // repaint request anyway. + std::atomic ui_thread_paint_requested_{false}; + + std::mutex guest_output_paint_config_mutex_; + // UI thread: writable, guest output thread: read-only. + GuestOutputPaintConfig guest_output_paint_config_; + + // Single-producer-multiple-consumers (lock-free SPSC + consumer lock) mailbox + // for presenting of the most up-to-date guest output image without long + // interlocking between guest output refreshing and painting. + static_assert(kGuestOutputMailboxSize == 3); + // The "acquired" image (in bits 0:1) is the one that is currently being read, + // or was last read, by a consumer of the guest output. The index of it can be + // modified only by the consumer and stays the same while it's processing the + // image. + // The "ready" image (in bits 2:3) is the most up-to-date image that the + // refresher has completely written, and a consumer may acquire it. It may be + // == acquired if there has been no refresh since the last acquisition. + // These two images can be accessed by painting in parallel, in an unordered + // way, with guest output refreshing. + std::atomic guest_output_mailbox_acquired_and_ready_{0}; + // The "writable" image is different than both "acquired" and "ready" and is + // accessible only by the guest output refreshing - it's the image that the + // refresher may write to. + uint32_t guest_output_mailbox_writable_ = 1; + // The guest output images may be consumed by two operations - painting, and + // capturing to a CPU-side buffer. These two usually never happen in parallel + // in reality though, as they're usually not even needed both at once in the + // same app within Xenia, so there's no need to create any + // complex lock-free synchronization between the two, but still, the situation + // when multiple consumers want the guest output image at the same is + // perfectly valid (unlike for producers, because even with a producer lock + // that would still be a race condition since the two refreshes themselves + // will be done in an undefined order) - so, a sufficient synchronization + // mechanism is used to make sure multiple consumers can acquire images + // without interfering with each other. + // While this is held, paint_mode_mutex_ must not be locked (the lock order is + // the reverse when painting in the guest output thread - painting is done + // with paint_mode_mutex_ held in this case, and guest output consumption + // happens as part of painting. + std::mutex guest_output_mailbox_consumer_mutex_; + + std::array + guest_output_properties_; + // Accessible only by refreshing, whether the last refresh contained an image + // rather than being blank. + bool guest_output_active_last_refresh_ = false; + + // Ordered by the Z order, and then by the time of addition. + // Note: All the iteration logic involving this Z ordering must be the same as + // in input handling (in the input listeners in the Window), but in reverse. + std::multimap ui_drawers_; + + size_t ui_draw_current_ = 0; + size_t ui_draw_current_z_order_; + std::multimap::iterator ui_draw_next_iterator_; + bool is_executing_ui_drawers_ = false; + + // Whether currently running the logic of PaintFromUIThread, so certain + // actions (such as changing the paint mode, requesting a redraw) must be + // deferred and be handled by the tail of PaintFromUIThread for consistency + // with what PaintFromUIThread does internally. + bool is_in_ui_thread_paint_ = false; + bool request_guest_output_paint_after_current_ui_thread_paint_; + bool request_ui_paint_after_current_ui_thread_paint_; + + // Platform-specific, but implementation-agnostic parts, primarily for + // limiting of the frame rate of the UI to avoid drawing the UI at extreme + // frame rates wasting the CPU and the GPU resources and starving everything + // else. The waits performed here must be interruptible by guest output + // presentation requests to prevent adding arbitrary amounts of latency to it. + // On Android and GTK, this is not needed, the frame rate of draw events is + // limited to the display refresh rate internally. +#if XE_PLATFORM_WIN32 + static Microsoft::WRL::ComPtr GetDXGIOutputForMonitor( + IDXGIFactory1* factory, HMONITOR monitor); + bool AreDXGIUITicksWaitable( + [[maybe_unused]] const std::unique_lock& dxgi_ui_tick_lock) { + return dxgi_ui_ticks_needed_ && !dxgi_ui_tick_thread_shutdown_ && + dxgi_ui_tick_output_; + } + void DXGIUITickThread(); + + // Accessible only from the UI thread, to avoid updating monitor-dependent + // information such as the DXGI output if the monitor hasn't actually been + // changed in the current state change (such as window positioning changes). + HMONITOR surface_win32_monitor_ = nullptr; + + // Requiring the lowest version of DXGI for IDXGIOutput::WaitForVBlank, which + // is available even on Windows Vista, but for IDXGIFactory1::IsCurrent, + // DXGI 1.1 is needed (available starting from Windows 7; also mixing DXGI 1.0 + // and 1.1+ in the Direct3D 12 code is not supported, see CreateDXGIFactory on + // MSDN). The factory is created when it's needed, and may be released and + // recreated when it's not current anymore and that becomes relevant. + Microsoft::WRL::ComPtr dxgi_ui_tick_factory_; + + // Accessible only from the UI thread, though the value is taken from the + // tick-mutex-protected variable. + uint64_t dxgi_ui_tick_last_draw_ = 0; + + std::mutex dxgi_ui_tick_mutex_; + uint64_t dxgi_ui_tick_last_vblank_ = 1; + // If output is null or shutdown is true, the signal may not be sent, either + // don't limit the frame rate in this case (an exceptional situation, such as + // a failure to find the output in DXGI), or don't draw at all if the window + // was removed from a connected monitor. + Microsoft::WRL::ComPtr dxgi_ui_tick_output_; + // To avoid allocating processing resources to the thread when nothing needs + // the ticks (not drawing the UI), the thread waits for vertical blanking + // intervals only when the UI drawing ticks are needed, and sleeping waiting + // for the control condition variable signals otherwise. Modifiable only from + // the UI thread, so readable by it without locking the mutex. + bool dxgi_ui_ticks_needed_ = false; + // The shutdown flag is modifiable only from the UI thread. + bool dxgi_ui_tick_thread_shutdown_ = false; + bool dxgi_ui_tick_force_requested_ = false; + + std::condition_variable dxgi_ui_tick_control_condition_; + // May be signaled by guest output refreshing. + std::condition_variable dxgi_ui_tick_signal_condition_; + + std::thread dxgi_ui_tick_thread_; +#endif // XE_PLATFORM +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_PRESENTER_H_ diff --git a/src/xenia/ui/renderdoc_api.cc b/src/xenia/ui/renderdoc_api.cc new file mode 100644 index 000000000..7c5f7ef99 --- /dev/null +++ b/src/xenia/ui/renderdoc_api.cc @@ -0,0 +1,76 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/renderdoc_api.h" + +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" +#include "xenia/base/platform.h" + +#if XE_PLATFORM_LINUX +#include +#elif XE_PLATFORM_WIN32 +#include "xenia/base/platform_win.h" +#endif + +namespace xe { +namespace ui { + +bool RenderdocApi::Initialize() { + Shutdown(); + pRENDERDOC_GetAPI get_api = nullptr; + // The RenderDoc library should be already loaded into the process if + // RenderDoc is attached - this is why RTLD_NOLOAD or GetModuleHandle instead + // of LoadLibrary. +#if XE_PLATFORM_LINUX +#if XE_PLATFORM_ANDROID + const char* librenderdoc_name = "libVkLayer_GLES_RenderDoc.so"; +#else + const char* librenderdoc_name = "librenderdoc.so"; +#endif + library_ = dlopen(librenderdoc_name, RTLD_NOW | RTLD_NOLOAD); + if (library_) { + get_api = pRENDERDOC_GetAPI(dlsym(library_, "RENDERDOC_GetAPI")); + } +#elif XE_PLATFORM_WIN32 + library_ = GetModuleHandleA("renderdoc.dll"); + if (library_) { + get_api = pRENDERDOC_GetAPI( + GetProcAddress(HMODULE(library_), "RENDERDOC_GetAPI")); + } +#endif + if (!get_api) { + Shutdown(); + return false; + } + // get_api will be null if RenderDoc is not attached, or the API isn't + // available on this platform, or there was an error. + if (!get_api || !get_api(eRENDERDOC_API_Version_1_0_0, (void**)&api_1_0_0_) || + !api_1_0_0_) { + Shutdown(); + return false; + } + XELOGI("RenderDoc API initialized"); + return true; +} + +void RenderdocApi::Shutdown() { + api_1_0_0_ = nullptr; + if (library_) { +#if XE_PLATFORM_LINUX + dlclose(library_); +#endif + // Not calling FreeLibrary on Windows as GetModuleHandle doesn't increment + // the reference count. + library_ = nullptr; + } +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/renderdoc_api.h b/src/xenia/ui/renderdoc_api.h new file mode 100644 index 000000000..1a07fe116 --- /dev/null +++ b/src/xenia/ui/renderdoc_api.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_RENDERDOC_API_H_ +#define XENIA_UI_RENDERDOC_API_H_ + +#include "third_party/renderdoc/renderdoc_app.h" + +namespace xe { +namespace ui { + +class RenderdocApi { + public: + RenderdocApi() = default; + RenderdocApi(const RenderdocApi& renderdoc_api) = delete; + RenderdocApi& operator=(const RenderdocApi& renderdoc_api) = delete; + ~RenderdocApi() { Shutdown(); } + + bool Initialize(); + void Shutdown(); + + // nullptr if not attached. + const RENDERDOC_API_1_0_0* api_1_0_0() const { return api_1_0_0_; } + + private: + void* library_ = nullptr; + const RENDERDOC_API_1_0_0* api_1_0_0_ = nullptr; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_RENDERDOC_API_H_ \ No newline at end of file diff --git a/src/xenia/ui/shaders/bytecode/.clang-format b/src/xenia/ui/shaders/bytecode/.clang-format index e3845288a..9d159247d 100644 --- a/src/xenia/ui/shaders/bytecode/.clang-format +++ b/src/xenia/ui/shaders/bytecode/.clang-format @@ -1 +1,2 @@ DisableFormat: true +SortIncludes: false diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h new file mode 100644 index 000000000..3c22503d1 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h @@ -0,0 +1,1226 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeBilinearConstants +// { +// +// int2 xe_bilinear_output_offset; // Offset: 0 Size: 8 +// float2 xe_bilinear_output_size_inv;// Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_sampler_linear_clamp sampler NA NA S0 s0 1 +// xe_texture texture float3 2d T0 t0 1 +// XeBilinearConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.001003, 0, 0, 0}, + { 0.000881, 0, 0, 0}, + { 0.001693, 0, 0, 0}, + { -0.001555, 0, 0, 0}, + { 0.001279, 0, 0, 0}, + { -0.000605, 0, 0, 0}, + { 0.001065, 0, 0, 0}, + { -0.001386, 0, 0, 0}, + { 0.001356, 0, 0, 0}, + { 0.000513, 0, 0, 0}, + { 0.001218, 0, 0, 0}, + { -0.001601, 0, 0, 0}, + { 0.000590, 0, 0, 0}, + { -0.000283, 0, 0, 0}, + { 0.001111, 0, 0, 0}, + { -0.001417, 0, 0, 0}, + { 0.001448, 0, 0, 0}, + { -0.000544, 0, 0, 0}, + { 0.000130, 0, 0, 0}, + { -0.001203, 0, 0, 0}, + { 0.000437, 0, 0, 0}, + { -0.001049, 0, 0, 0}, + { 0.000620, 0, 0, 0}, + { -0.000483, 0, 0, 0}, + { 0.001877, 0, 0, 0}, + { -0.001095, 0, 0, 0}, + { -0.000100, 0, 0, 0}, + { -0.000528, 0, 0, 0}, + { 0.001432, 0, 0, 0}, + { -0.001938, 0, 0, 0}, + { -0.000697, 0, 0, 0}, + { 0.000038, 0, 0, 0}, + { 0.000712, 0, 0, 0}, + { -0.001310, 0, 0, 0}, + { 0.001095, 0, 0, 0}, + { -0.000299, 0, 0, 0}, + { 0.001754, 0, 0, 0}, + { -0.001677, 0, 0, 0}, + { 0.001478, 0, 0, 0}, + { -0.000038, 0, 0, 0}, + { 0.000789, 0, 0, 0}, + { -0.001831, 0, 0, 0}, + { 0.000299, 0, 0, 0}, + { 0.000988, 0, 0, 0}, + { -0.001172, 0, 0, 0}, + { 0.000176, 0, 0, 0}, + { 0.001647, 0, 0, 0}, + { -0.001585, 0, 0, 0}, + { 0.000345, 0, 0, 0}, + { 0.001861, 0, 0, 0}, + { -0.001769, 0, 0, 0}, + { -0.000866, 0, 0, 0}, + { 0.000896, 0, 0, 0}, + { 0.000161, 0, 0, 0}, + { -0.000927, 0, 0, 0}, + { -0.001524, 0, 0, 0}, + { -0.000651, 0, 0, 0}, + { 0.001294, 0, 0, 0}, + { -0.000804, 0, 0, 0}, + { -0.001463, 0, 0, 0}, + { 0.001800, 0, 0, 0}, + { -0.000850, 0, 0, 0}, + { 0.000850, 0, 0, 0}, + { -0.000452, 0, 0, 0}, + { -0.001065, 0, 0, 0}, + { -0.000146, 0, 0, 0}, + { 0.000237, 0, 0, 0}, + { 0.001417, 0, 0, 0}, + { -0.000590, 0, 0, 0}, + { -0.000191, 0, 0, 0}, + { 0.001601, 0, 0, 0}, + { 0.001019, 0, 0, 0}, + { 0.000406, 0, 0, 0}, + { -0.000207, 0, 0, 0}, + { 0.001585, 0, 0, 0}, + { 0.000651, 0, 0, 0}, + { -0.000069, 0, 0, 0}, + { 0.000421, 0, 0, 0}, + { -0.001647, 0, 0, 0}, + { 0.001371, 0, 0, 0}, + { 0.000927, 0, 0, 0}, + { -0.000666, 0, 0, 0}, + { 0.001187, 0, 0, 0}, + { -0.001448, 0, 0, 0}, + { 0.000574, 0, 0, 0}, + { -0.001892, 0, 0, 0}, + { 0.000758, 0, 0, 0}, + { -0.001294, 0, 0, 0}, + { 0.001922, 0, 0, 0}, + { -0.001662, 0, 0, 0}, + { -0.001034, 0, 0, 0}, + { -0.000498, 0, 0, 0}, + { -0.001861, 0, 0, 0}, + { 0.001203, 0, 0, 0}, + { -0.000329, 0, 0, 0}, + { -0.001371, 0, 0, 0}, + { 0.001631, 0, 0, 0}, + { -0.001846, 0, 0, 0}, + { 0.000728, 0, 0, 0}, + { -0.000911, 0, 0, 0}, + { 0.001815, 0, 0, 0}, + { -0.001141, 0, 0, 0}, + { -0.000375, 0, 0, 0}, + { 0.000100, 0, 0, 0}, + { -0.000743, 0, 0, 0}, + { 0.001172, 0, 0, 0}, + { 0.000069, 0, 0, 0}, + { 0.001494, 0, 0, 0}, + { 0.000973, 0, 0, 0}, + { -0.000957, 0, 0, 0}, + { 0.001938, 0, 0, 0}, + { 0.000528, 0, 0, 0}, + { 0.000054, 0, 0, 0}, + { -0.001248, 0, 0, 0}, + { -0.000268, 0, 0, 0}, + { 0.001540, 0, 0, 0}, + { -0.000008, 0, 0, 0}, + { 0.000314, 0, 0, 0}, + { 0.001340, 0, 0, 0}, + { -0.001754, 0, 0, 0}, + { 0.000498, 0, 0, 0}, + { -0.001187, 0, 0, 0}, + { 0.000774, 0, 0, 0}, + { -0.001340, 0, 0, 0}, + { 0.000268, 0, 0, 0}, + { -0.001478, 0, 0, 0}, + { -0.000130, 0, 0, 0}, + { -0.000774, 0, 0, 0}, + { 0.001310, 0, 0, 0}, + { 0.000391, 0, 0, 0}, + { 0.000957, 0, 0, 0}, + { -0.000467, 0, 0, 0}, + { -0.001540, 0, 0, 0}, + { 0.001034, 0, 0, 0}, + { -0.000682, 0, 0, 0}, + { 0.001677, 0, 0, 0}, + { 0.001003, 0, 0, 0}, + { -0.000421, 0, 0, 0}, + { 0.001785, 0, 0, 0}, + { -0.000237, 0, 0, 0}, + { -0.000620, 0, 0, 0}, + { 0.001662, 0, 0, 0}, + { 0.000835, 0, 0, 0}, + { -0.001723, 0, 0, 0}, + { -0.001080, 0, 0, 0}, + { 0.001769, 0, 0, 0}, + { -0.000789, 0, 0, 0}, + { -0.001785, 0, 0, 0}, + { 0.000682, 0, 0, 0}, + { -0.000988, 0, 0, 0}, + { -0.001325, 0, 0, 0}, + { -0.000176, 0, 0, 0}, + { -0.001509, 0, 0, 0}, + { 0.000329, 0, 0, 0}, + { -0.001953, 0, 0, 0}, + { 0.000666, 0, 0, 0}, + { -0.001616, 0, 0, 0}, + { 0.001157, 0, 0, 0}, + { 0.000452, 0, 0, 0}, + { -0.000437, 0, 0, 0}, + { 0.000191, 0, 0, 0}, + { -0.001494, 0, 0, 0}, + { 0.001141, 0, 0, 0}, + { 0.000084, 0, 0, 0}, + { 0.001892, 0, 0, 0}, + { 0.001402, 0, 0, 0}, + { 0.000559, 0, 0, 0}, + { 0.000115, 0, 0, 0}, + { 0.001264, 0, 0, 0}, + { -0.000574, 0, 0, 0}, + { -0.000973, 0, 0, 0}, + { 0.001325, 0, 0, 0}, + { 0.000222, 0, 0, 0}, + { -0.000758, 0, 0, 0}, + { -0.001356, 0, 0, 0}, + { 0.001463, 0, 0, 0}, + { 0.000866, 0, 0, 0}, + { -0.000360, 0, 0, 0}, + { 0.000544, 0, 0, 0}, + { -0.001126, 0, 0, 0}, + { -0.000253, 0, 0, 0}, + { -0.000559, 0, 0, 0}, + { -0.001815, 0, 0, 0}, + { 0.001723, 0, 0, 0}, + { -0.001157, 0, 0, 0}, + { 0.000743, 0, 0, 0}, + { 0.001570, 0, 0, 0}, + { -0.000115, 0, 0, 0}, + { -0.001218, 0, 0, 0}, + { 0.001831, 0, 0, 0}, + { 0.000023, 0, 0, 0}, + { -0.001922, 0, 0, 0}, + { 0.001739, 0, 0, 0}, + { -0.000712, 0, 0, 0}, + { 0.001555, 0, 0, 0}, + { -0.001708, 0, 0, 0}, + { 0.001233, 0, 0, 0}, + { 0.000207, 0, 0, 0}, + { 0.001049, 0, 0, 0}, + { -0.000728, 0, 0, 0}, + { -0.001631, 0, 0, 0}, + { -0.000314, 0, 0, 0}, + { 0.000483, 0, 0, 0}, + { -0.001800, 0, 0, 0}, + { 0.000942, 0, 0, 0}, + { -0.000345, 0, 0, 0}, + { 0.000697, 0, 0, 0}, + { -0.001019, 0, 0, 0}, + { -0.001570, 0, 0, 0}, + { -0.000023, 0, 0, 0}, + { -0.001279, 0, 0, 0}, + { 0.000804, 0, 0, 0}, + { -0.000896, 0, 0, 0}, + { -0.001432, 0, 0, 0}, + { 0.000605, 0, 0, 0}, + { -0.000084, 0, 0, 0}, + { 0.000911, 0, 0, 0}, + { 0.001953, 0, 0, 0}, + { -0.001402, 0, 0, 0}, + { -0.000636, 0, 0, 0}, + { 0.001509, 0, 0, 0}, + { -0.000820, 0, 0, 0}, + { 0.001248, 0, 0, 0}, + { 0.000253, 0, 0, 0}, + { 0.001524, 0, 0, 0}, + { 0.001126, 0, 0, 0}, + { 0.000360, 0, 0, 0}, + { -0.000391, 0, 0, 0}, + { 0.001907, 0, 0, 0}, + { 0.001386, 0, 0, 0}, + { -0.001111, 0, 0, 0}, + { 0.001616, 0, 0, 0}, + { -0.000881, 0, 0, 0}, + { 0.000146, 0, 0, 0}, + { 0.001080, 0, 0, 0}, + { -0.000054, 0, 0, 0}, + { 0.000283, 0, 0, 0}, + { -0.001693, 0, 0, 0}, + { -0.001264, 0, 0, 0}, + { -0.000513, 0, 0, 0}, + { -0.000161, 0, 0, 0}, + { -0.001877, 0, 0, 0}, + { -0.000835, 0, 0, 0}, + { 0.000636, 0, 0, 0}, + { 0.000008, 0, 0, 0}, + { -0.001907, 0, 0, 0}, + { -0.000222, 0, 0, 0}, + { 0.000375, 0, 0, 0}, + { -0.001739, 0, 0, 0}, + { -0.000406, 0, 0, 0}, + { -0.001233, 0, 0, 0}, + { 0.001708, 0, 0, 0}, + { -0.000942, 0, 0, 0}, + { 0.000820, 0, 0, 0}, + { 0.001846, 0, 0, 0}, + { 0.000467, 0, 0, 0} } +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_sampler S0[0:0], mode_default, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 2 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +utof r0.zw, r0.xxxy +add r0.zw, r0.zzzw, l(0.000000, 0.000000, 0.500000, 0.500000) +mul r0.zw, r0.zzzw, CB0[0][0].zzzw +sample_l r1.xyz, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +bfi r0.y, l(4), l(4), r0.y, l(0) +bfi r0.x, l(4), l(0), r0.x, r0.y +add o0.xyz, r1.xyzx, icb[r0.x + 0].xxxx +mov o0.w, l(1.000000) +ret +// Approximately 11 instruction slots used +#endif + +const BYTE guest_output_bilinear_dither_ps[] = +{ + 68, 88, 66, 67, 238, 251, + 7, 36, 12, 102, 119, 199, + 78, 59, 74, 185, 195, 243, + 55, 64, 1, 0, 0, 0, + 56, 21, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 68, 2, 0, 0, 120, 2, + 0, 0, 172, 2, 0, 0, + 156, 20, 0, 0, 82, 68, + 69, 70, 8, 2, 0, 0, + 1, 0, 0, 0, 236, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 224, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 180, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 120, 101, 95, 115, 97, 109, + 112, 108, 101, 114, 95, 108, + 105, 110, 101, 97, 114, 95, + 99, 108, 97, 109, 112, 0, + 120, 101, 95, 116, 101, 120, + 116, 117, 114, 101, 0, 88, + 101, 66, 105, 108, 105, 110, + 101, 97, 114, 67, 111, 110, + 115, 116, 97, 110, 116, 115, + 0, 171, 215, 0, 0, 0, + 2, 0, 0, 0, 4, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 84, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 116, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 152, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 188, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 120, 101, + 95, 98, 105, 108, 105, 110, + 101, 97, 114, 95, 111, 117, + 116, 112, 117, 116, 95, 111, + 102, 102, 115, 101, 116, 0, + 105, 110, 116, 50, 0, 171, + 1, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 110, 1, 0, 0, + 120, 101, 95, 98, 105, 108, + 105, 110, 101, 97, 114, 95, + 111, 117, 116, 112, 117, 116, + 95, 115, 105, 122, 101, 95, + 105, 110, 118, 0, 102, 108, + 111, 97, 116, 50, 0, 171, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 1, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 3, + 0, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 232, 17, + 0, 0, 81, 0, 0, 0, + 122, 4, 0, 0, 106, 8, + 0, 1, 53, 24, 0, 0, + 2, 4, 0, 0, 132, 131, + 131, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 231, 230, 102, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 222, 221, 221, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 203, + 203, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 168, 167, 167, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 158, 30, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 140, 139, + 139, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 182, 181, 181, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 178, 177, 177, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 134, + 6, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 160, 159, 159, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 210, 209, 209, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 155, 154, + 26, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 149, 148, 148, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 145, 145, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 186, 185, + 185, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 190, 189, 189, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 143, 142, 14, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, + 8, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 158, 157, 157, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 229, 228, 228, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 137, + 137, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 163, 162, 34, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 253, 252, 252, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 246, 245, + 245, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 144, 143, 143, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 209, 208, 208, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 138, + 10, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 188, 187, 187, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 254, 253, 253, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 183, 182, + 54, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 161, 160, 32, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 187, 186, 58, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 172, 171, + 171, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 144, 143, 143, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 157, 156, 156, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 230, 229, + 229, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 220, 219, 219, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 194, 193, 193, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 160, + 32, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 207, 206, 78, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 240, 239, 239, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 157, 156, + 156, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 130, 129, 129, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 154, 153, 153, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 185, 184, + 56, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 216, 215, 215, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 208, 207, 207, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 181, 180, + 180, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 244, 243, 243, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 231, 231, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 227, 226, + 98, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 235, 234, 106, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 169, 168, 40, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 243, 242, + 114, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 200, 199, 199, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 171, 170, 42, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 169, + 169, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 211, 210, 82, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 192, 191, 191, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 235, + 235, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 223, 222, 94, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 223, 222, 94, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 236, + 236, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 139, 139, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 153, 152, 24, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 249, 248, + 120, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 186, 185, 185, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 155, 154, 26, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 201, 200, + 72, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 210, 209, 209, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 134, 133, 133, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 212, + 212, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 217, 216, 88, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 208, 207, 207, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 171, 170, + 42, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 145, 144, 144, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 220, 220, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 216, 215, + 215, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 179, 179, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 243, 242, 114, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 175, 174, + 46, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 156, 155, 155, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 190, 189, 189, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 150, + 22, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 248, 247, 247, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 199, 198, 70, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 169, + 169, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 252, 251, 251, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 218, 217, 217, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 135, + 135, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 131, 130, 2, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 244, 243, 243, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 158, 157, + 157, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 173, 172, 172, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 180, 179, 179, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 213, + 213, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 242, 241, 241, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 191, 190, 62, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 238, + 110, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 238, 237, 237, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 150, 149, 149, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 197, 196, + 196, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 209, 208, 208, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 194, 66, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 154, 153, + 153, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 145, 144, 144, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 196, 195, 195, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 254, + 126, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 251, 250, 122, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 254, 253, 253, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 138, + 10, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 225, 224, 96, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 164, 163, 163, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 140, + 140, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 202, 201, 201, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 129, 128, 0, 183, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 164, + 164, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 176, 175, 175, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 230, 229, 229, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 131, 130, + 2, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 156, 155, 155, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 203, 202, 74, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 176, 175, + 175, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 141, 140, 140, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 194, 193, 193, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, + 8, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 203, 202, 74, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 172, 171, 171, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 205, 204, + 204, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 251, 250, 122, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 245, 244, 244, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 202, 201, + 201, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 136, 135, 135, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 179, 178, 50, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 220, 219, + 219, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 132, 131, 131, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 220, 220, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 233, + 233, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 249, 248, 120, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 163, 162, 34, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 218, 217, + 217, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 219, 218, 90, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 226, 225, 225, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 141, + 141, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 232, 231, 231, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 207, 206, 78, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 233, + 233, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 179, 178, 50, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 130, 129, 129, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 173, + 173, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 185, 184, 56, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 198, 197, 197, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 172, + 172, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 187, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 175, 174, 46, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 211, + 211, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 152, 151, 151, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 237, 236, 236, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 228, + 228, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 201, 200, 72, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 196, 195, 195, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 149, + 149, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 177, 176, 176, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 248, 247, 247, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 184, 183, + 183, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 147, 146, 18, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 241, 240, 240, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 166, 165, + 165, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 151, 150, 22, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 254, 126, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 173, + 173, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 233, 232, 104, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 199, 198, 70, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 178, 177, + 177, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 192, 191, 191, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 227, 226, 98, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 188, + 188, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 143, 142, 14, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 147, 147, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 133, 132, + 132, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 147, 146, 18, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 238, 237, 237, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 226, 225, + 225, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 152, 151, 151, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 194, 66, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 205, + 205, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 241, 240, 240, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 160, 159, 159, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 240, 239, + 239, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 193, 192, 192, 55, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 252, 251, 251, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 228, 227, + 227, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 187, 186, 58, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 204, 203, 203, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 224, 223, + 223, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 162, 161, 161, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 217, 216, 88, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 137, + 137, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 191, 190, 62, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 214, 213, 213, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 164, + 164, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 253, 252, 252, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 236, 235, 235, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 247, 246, + 118, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 181, 180, 180, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 183, 182, 54, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 134, 133, + 133, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 206, 205, 205, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 193, 192, 192, 183, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 168, 167, + 167, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 211, 210, 82, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 235, 234, 106, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 188, 187, + 187, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 159, 158, 30, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 177, 176, 176, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 238, + 110, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 59, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 184, 183, 183, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 166, + 38, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 198, 197, 197, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 215, 214, 86, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 163, + 163, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 133, 132, 132, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 200, 199, 199, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 148, 147, + 147, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 189, 188, 188, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 205, 204, 204, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 250, 249, + 249, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 182, 181, 181, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 145, 145, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 211, + 211, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 231, 230, 102, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 153, 152, 24, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 141, + 141, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 225, 224, 96, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 149, 148, 148, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 222, 221, + 221, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 166, 165, 165, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 135, 134, 6, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 168, + 40, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 246, 245, 245, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 219, 218, 90, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 166, + 38, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 129, 128, 0, 55, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 250, 249, 249, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 233, 232, + 104, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 197, 196, 196, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 228, 227, 227, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 212, + 212, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 162, 161, 161, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 224, 223, 223, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 247, 246, + 118, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 214, 86, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 242, 241, 241, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 245, 244, + 244, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 89, 0, 0, 7, + 70, 142, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 90, 0, 0, 6, 70, 110, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 88, 24, 0, 7, 70, 126, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 0, 0, 0, 0, 100, 32, + 0, 4, 50, 16, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 27, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 4, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 166, 14, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 56, 0, + 0, 9, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 14, + 16, 0, 0, 0, 0, 0, + 166, 142, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, + 0, 13, 114, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 140, 0, 0, 11, + 34, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 140, 0, + 0, 11, 18, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 6, 144, 144, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 11, 0, + 0, 0, 2, 0, 0, 0, + 0, 1, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h similarity index 53% rename from src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h rename to src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h index b0ff6436a..c12024a7a 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h @@ -5,10 +5,11 @@ // // Buffer Definitions: // -// cbuffer XeStretchGammaRootConstants +// cbuffer XeBilinearConstants // { // -// float xe_gamma_ramp_inv_size; // Offset: 0 Size: 4 +// int2 xe_bilinear_output_offset; // Offset: 0 Size: 8 +// float2 xe_bilinear_output_size_inv;// Offset: 8 Size: 8 // // } // @@ -19,8 +20,7 @@ // ------------------------------ ---------- ------- ----------- ------- -------------- ------ // xe_sampler_linear_clamp sampler NA NA S0 s0 1 // xe_texture texture float3 2d T0 t0 1 -// xe_gamma_ramp texture float3 1d T1 t1 1 -// XeStretchGammaRootConstants cbuffer NA NA CB0 cb0 1 +// XeBilinearConstants cbuffer NA NA CB0 cb0 1 // // // @@ -28,7 +28,7 @@ // // Name Index Mask Register SysValue Format Used // -------------------- ----- ------ -------- -------- ------- ------ -// TEXCOORD 0 xy 0 NONE float xy +// SV_Position 0 xyzw 0 POS float xy // // // Output signature: @@ -42,107 +42,113 @@ dcl_globalFlags refactoringAllowed dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 dcl_sampler S0[0:0], mode_default, space=0 dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 -dcl_resource_texture1d (float,float,float,float) T1[1:1], space=0 -dcl_input_ps linear v0.xy +dcl_input_ps_siv linear noperspective v0.xy, position dcl_output o0.xyzw -dcl_temps 2 -sample_l r0.xyz, v0.xyxx, T0[0].xyzw, S0[0], l(0.000000) -add r0.w, -CB0[0][0].x, l(1.000000) -mul r1.x, CB0[0][0].x, l(0.500000) -mad r0.xyz, r0.xyzx, r0.wwww, r1.xxxx -sample_l r0.x, r0.x, T1[1].xyzw, S0[0], l(0.000000) -sample_l r0.y, r0.y, T1[1].xyzw, S0[0], l(0.000000) -sample_l r0.z, r0.z, T1[1].xyzw, S0[0], l(0.000000) +dcl_temps 1 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +utof r0.xy, r0.xyxx +add r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000) +mul r0.xy, r0.xyxx, CB0[0][0].zwzz +sample_l r0.xyz, r0.xyxx, T0[0].xyzw, S0[0], l(0.000000) mov o0.xyz, r0.xyzx mov o0.w, l(1.000000) ret -// Approximately 10 instruction slots used +// Approximately 9 instruction slots used #endif -const BYTE stretch_gamma_ps[] = +const BYTE guest_output_bilinear_ps[] = { - 68, 88, 66, 67, 4, 222, - 150, 161, 149, 185, 43, 51, - 177, 110, 80, 244, 108, 113, - 108, 20, 1, 0, 0, 0, - 36, 5, 0, 0, 5, 0, + 68, 88, 66, 67, 195, 73, + 6, 106, 30, 227, 35, 134, + 146, 186, 4, 157, 98, 172, + 18, 157, 1, 0, 0, 0, + 204, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, - 20, 2, 0, 0, 72, 2, - 0, 0, 124, 2, 0, 0, - 136, 4, 0, 0, 82, 68, - 69, 70, 216, 1, 0, 0, - 1, 0, 0, 0, 44, 1, - 0, 0, 4, 0, 0, 0, + 68, 2, 0, 0, 120, 2, + 0, 0, 172, 2, 0, 0, + 48, 4, 0, 0, 82, 68, + 69, 70, 8, 2, 0, 0, + 1, 0, 0, 0, 236, 0, + 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, - 176, 1, 0, 0, 19, 19, + 255, 255, 0, 5, 0, 0, + 224, 1, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 36, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, - 220, 0, 0, 0, 3, 0, + 180, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 244, 0, + 0, 0, 0, 0, 204, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 255, 0, 0, 0, - 2, 0, 0, 0, 5, 0, + 0, 0, 215, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 120, 101, 95, 115, 97, 109, + 112, 108, 101, 114, 95, 108, + 105, 110, 101, 97, 114, 95, + 99, 108, 97, 109, 112, 0, + 120, 101, 95, 116, 101, 120, + 116, 117, 114, 101, 0, 88, + 101, 66, 105, 108, 105, 110, + 101, 97, 114, 67, 111, 110, + 115, 116, 97, 110, 116, 115, + 0, 171, 215, 0, 0, 0, + 2, 0, 0, 0, 4, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 84, 1, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, - 255, 255, 255, 255, 1, 0, - 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 13, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 120, 101, - 95, 115, 97, 109, 112, 108, - 101, 114, 95, 108, 105, 110, - 101, 97, 114, 95, 99, 108, - 97, 109, 112, 0, 120, 101, - 95, 116, 101, 120, 116, 117, - 114, 101, 0, 120, 101, 95, - 103, 97, 109, 109, 97, 95, - 114, 97, 109, 112, 0, 88, - 101, 83, 116, 114, 101, 116, - 99, 104, 71, 97, 109, 109, - 97, 82, 111, 111, 116, 67, - 111, 110, 115, 116, 97, 110, - 116, 115, 0, 171, 171, 171, - 13, 1, 0, 0, 1, 0, - 0, 0, 68, 1, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 108, 1, 0, 0, 0, 0, - 0, 0, 4, 0, 0, 0, - 2, 0, 0, 0, 140, 1, + 116, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 152, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 188, 1, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 120, 101, - 95, 103, 97, 109, 109, 97, - 95, 114, 97, 109, 112, 95, - 105, 110, 118, 95, 115, 105, - 122, 101, 0, 102, 108, 111, - 97, 116, 0, 171, 171, 171, - 0, 0, 3, 0, 1, 0, - 1, 0, 0, 0, 0, 0, + 95, 98, 105, 108, 105, 110, + 101, 97, 114, 95, 111, 117, + 116, 112, 117, 116, 95, 111, + 102, 102, 115, 101, 116, 0, + 105, 110, 116, 50, 0, 171, + 1, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 131, 1, 0, 0, + 0, 0, 110, 1, 0, 0, + 120, 101, 95, 98, 105, 108, + 105, 110, 101, 97, 114, 95, + 111, 117, 116, 112, 117, 116, + 95, 115, 105, 122, 101, 95, + 105, 110, 118, 0, 102, 108, + 111, 97, 116, 50, 0, 171, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 1, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, @@ -153,12 +159,12 @@ const BYTE stretch_gamma_ps[] = 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 3, 3, - 0, 0, 84, 69, 88, 67, - 79, 79, 82, 68, 0, 171, - 171, 171, 79, 83, 71, 78, + 0, 0, 0, 0, 15, 3, + 0, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, @@ -167,9 +173,9 @@ const BYTE stretch_gamma_ps[] = 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 97, 114, 103, 101, 116, 0, 171, 171, - 83, 72, 69, 88, 4, 2, + 83, 72, 69, 88, 124, 1, 0, 0, 81, 0, 0, 0, - 129, 0, 0, 0, 106, 8, + 95, 0, 0, 0, 106, 8, 0, 1, 89, 0, 0, 7, 70, 142, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -183,92 +189,71 @@ const BYTE stretch_gamma_ps[] = 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 0, 0, - 0, 0, 0, 0, 88, 16, - 0, 7, 70, 126, 48, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, - 85, 85, 0, 0, 0, 0, - 0, 0, 98, 16, 0, 3, - 50, 16, 16, 0, 0, 0, + 0, 0, 0, 0, 100, 32, + 0, 4, 50, 16, 16, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, - 2, 0, 0, 0, 72, 0, - 0, 13, 114, 0, 16, 0, + 1, 0, 0, 0, 27, 0, + 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 9, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 230, 138, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, + 0, 13, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, 70, 126, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, - 130, 0, 16, 0, 0, 0, - 0, 0, 10, 128, 48, 128, - 65, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, - 56, 0, 0, 9, 18, 0, - 16, 0, 1, 0, 0, 0, - 10, 128, 48, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 0, 63, - 50, 0, 0, 9, 114, 0, - 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, - 0, 0, 246, 15, 16, 0, - 0, 0, 0, 0, 6, 0, - 16, 0, 1, 0, 0, 0, - 72, 0, 0, 13, 18, 0, - 16, 0, 0, 0, 0, 0, - 10, 0, 16, 0, 0, 0, - 0, 0, 70, 126, 32, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 0, 96, 32, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 64, 0, 0, - 0, 0, 0, 0, 72, 0, - 0, 13, 34, 0, 16, 0, - 0, 0, 0, 0, 26, 0, - 16, 0, 0, 0, 0, 0, - 70, 126, 32, 0, 1, 0, + 2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, - 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 1, 64, 0, 0, 0, 0, - 0, 0, 72, 0, 0, 13, - 66, 0, 16, 0, 0, 0, - 0, 0, 42, 0, 16, 0, - 0, 0, 0, 0, 70, 126, - 32, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 96, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, - 54, 0, 0, 5, 114, 32, - 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, - 0, 0, 54, 0, 0, 5, - 130, 32, 16, 0, 0, 0, - 0, 0, 1, 64, 0, 0, - 0, 0, 128, 63, 62, 0, - 0, 1, 83, 84, 65, 84, - 148, 0, 0, 0, 10, 0, - 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, - 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -278,7 +263,5 @@ const BYTE stretch_gamma_ps[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0 + 0, 0, 0, 0 }; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h new file mode 100644 index 000000000..924aed761 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h @@ -0,0 +1,2227 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeCasResampleConstants +// { +// +// int2 xe_cas_output_offset; // Offset: 0 Size: 8 +// float2 xe_cas_input_output_size_ratio;// Offset: 8 Size: 8 +// float xe_cas_sharpness_post_setup; // Offset: 16 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeCasResampleConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.001003, 0, 0, 0}, + { 0.000881, 0, 0, 0}, + { 0.001693, 0, 0, 0}, + { -0.001555, 0, 0, 0}, + { 0.001279, 0, 0, 0}, + { -0.000605, 0, 0, 0}, + { 0.001065, 0, 0, 0}, + { -0.001386, 0, 0, 0}, + { 0.001356, 0, 0, 0}, + { 0.000513, 0, 0, 0}, + { 0.001218, 0, 0, 0}, + { -0.001601, 0, 0, 0}, + { 0.000590, 0, 0, 0}, + { -0.000283, 0, 0, 0}, + { 0.001111, 0, 0, 0}, + { -0.001417, 0, 0, 0}, + { 0.001448, 0, 0, 0}, + { -0.000544, 0, 0, 0}, + { 0.000130, 0, 0, 0}, + { -0.001203, 0, 0, 0}, + { 0.000437, 0, 0, 0}, + { -0.001049, 0, 0, 0}, + { 0.000620, 0, 0, 0}, + { -0.000483, 0, 0, 0}, + { 0.001877, 0, 0, 0}, + { -0.001095, 0, 0, 0}, + { -0.000100, 0, 0, 0}, + { -0.000528, 0, 0, 0}, + { 0.001432, 0, 0, 0}, + { -0.001938, 0, 0, 0}, + { -0.000697, 0, 0, 0}, + { 0.000038, 0, 0, 0}, + { 0.000712, 0, 0, 0}, + { -0.001310, 0, 0, 0}, + { 0.001095, 0, 0, 0}, + { -0.000299, 0, 0, 0}, + { 0.001754, 0, 0, 0}, + { -0.001677, 0, 0, 0}, + { 0.001478, 0, 0, 0}, + { -0.000038, 0, 0, 0}, + { 0.000789, 0, 0, 0}, + { -0.001831, 0, 0, 0}, + { 0.000299, 0, 0, 0}, + { 0.000988, 0, 0, 0}, + { -0.001172, 0, 0, 0}, + { 0.000176, 0, 0, 0}, + { 0.001647, 0, 0, 0}, + { -0.001585, 0, 0, 0}, + { 0.000345, 0, 0, 0}, + { 0.001861, 0, 0, 0}, + { -0.001769, 0, 0, 0}, + { -0.000866, 0, 0, 0}, + { 0.000896, 0, 0, 0}, + { 0.000161, 0, 0, 0}, + { -0.000927, 0, 0, 0}, + { -0.001524, 0, 0, 0}, + { -0.000651, 0, 0, 0}, + { 0.001294, 0, 0, 0}, + { -0.000804, 0, 0, 0}, + { -0.001463, 0, 0, 0}, + { 0.001800, 0, 0, 0}, + { -0.000850, 0, 0, 0}, + { 0.000850, 0, 0, 0}, + { -0.000452, 0, 0, 0}, + { -0.001065, 0, 0, 0}, + { -0.000146, 0, 0, 0}, + { 0.000237, 0, 0, 0}, + { 0.001417, 0, 0, 0}, + { -0.000590, 0, 0, 0}, + { -0.000191, 0, 0, 0}, + { 0.001601, 0, 0, 0}, + { 0.001019, 0, 0, 0}, + { 0.000406, 0, 0, 0}, + { -0.000207, 0, 0, 0}, + { 0.001585, 0, 0, 0}, + { 0.000651, 0, 0, 0}, + { -0.000069, 0, 0, 0}, + { 0.000421, 0, 0, 0}, + { -0.001647, 0, 0, 0}, + { 0.001371, 0, 0, 0}, + { 0.000927, 0, 0, 0}, + { -0.000666, 0, 0, 0}, + { 0.001187, 0, 0, 0}, + { -0.001448, 0, 0, 0}, + { 0.000574, 0, 0, 0}, + { -0.001892, 0, 0, 0}, + { 0.000758, 0, 0, 0}, + { -0.001294, 0, 0, 0}, + { 0.001922, 0, 0, 0}, + { -0.001662, 0, 0, 0}, + { -0.001034, 0, 0, 0}, + { -0.000498, 0, 0, 0}, + { -0.001861, 0, 0, 0}, + { 0.001203, 0, 0, 0}, + { -0.000329, 0, 0, 0}, + { -0.001371, 0, 0, 0}, + { 0.001631, 0, 0, 0}, + { -0.001846, 0, 0, 0}, + { 0.000728, 0, 0, 0}, + { -0.000911, 0, 0, 0}, + { 0.001815, 0, 0, 0}, + { -0.001141, 0, 0, 0}, + { -0.000375, 0, 0, 0}, + { 0.000100, 0, 0, 0}, + { -0.000743, 0, 0, 0}, + { 0.001172, 0, 0, 0}, + { 0.000069, 0, 0, 0}, + { 0.001494, 0, 0, 0}, + { 0.000973, 0, 0, 0}, + { -0.000957, 0, 0, 0}, + { 0.001938, 0, 0, 0}, + { 0.000528, 0, 0, 0}, + { 0.000054, 0, 0, 0}, + { -0.001248, 0, 0, 0}, + { -0.000268, 0, 0, 0}, + { 0.001540, 0, 0, 0}, + { -0.000008, 0, 0, 0}, + { 0.000314, 0, 0, 0}, + { 0.001340, 0, 0, 0}, + { -0.001754, 0, 0, 0}, + { 0.000498, 0, 0, 0}, + { -0.001187, 0, 0, 0}, + { 0.000774, 0, 0, 0}, + { -0.001340, 0, 0, 0}, + { 0.000268, 0, 0, 0}, + { -0.001478, 0, 0, 0}, + { -0.000130, 0, 0, 0}, + { -0.000774, 0, 0, 0}, + { 0.001310, 0, 0, 0}, + { 0.000391, 0, 0, 0}, + { 0.000957, 0, 0, 0}, + { -0.000467, 0, 0, 0}, + { -0.001540, 0, 0, 0}, + { 0.001034, 0, 0, 0}, + { -0.000682, 0, 0, 0}, + { 0.001677, 0, 0, 0}, + { 0.001003, 0, 0, 0}, + { -0.000421, 0, 0, 0}, + { 0.001785, 0, 0, 0}, + { -0.000237, 0, 0, 0}, + { -0.000620, 0, 0, 0}, + { 0.001662, 0, 0, 0}, + { 0.000835, 0, 0, 0}, + { -0.001723, 0, 0, 0}, + { -0.001080, 0, 0, 0}, + { 0.001769, 0, 0, 0}, + { -0.000789, 0, 0, 0}, + { -0.001785, 0, 0, 0}, + { 0.000682, 0, 0, 0}, + { -0.000988, 0, 0, 0}, + { -0.001325, 0, 0, 0}, + { -0.000176, 0, 0, 0}, + { -0.001509, 0, 0, 0}, + { 0.000329, 0, 0, 0}, + { -0.001953, 0, 0, 0}, + { 0.000666, 0, 0, 0}, + { -0.001616, 0, 0, 0}, + { 0.001157, 0, 0, 0}, + { 0.000452, 0, 0, 0}, + { -0.000437, 0, 0, 0}, + { 0.000191, 0, 0, 0}, + { -0.001494, 0, 0, 0}, + { 0.001141, 0, 0, 0}, + { 0.000084, 0, 0, 0}, + { 0.001892, 0, 0, 0}, + { 0.001402, 0, 0, 0}, + { 0.000559, 0, 0, 0}, + { 0.000115, 0, 0, 0}, + { 0.001264, 0, 0, 0}, + { -0.000574, 0, 0, 0}, + { -0.000973, 0, 0, 0}, + { 0.001325, 0, 0, 0}, + { 0.000222, 0, 0, 0}, + { -0.000758, 0, 0, 0}, + { -0.001356, 0, 0, 0}, + { 0.001463, 0, 0, 0}, + { 0.000866, 0, 0, 0}, + { -0.000360, 0, 0, 0}, + { 0.000544, 0, 0, 0}, + { -0.001126, 0, 0, 0}, + { -0.000253, 0, 0, 0}, + { -0.000559, 0, 0, 0}, + { -0.001815, 0, 0, 0}, + { 0.001723, 0, 0, 0}, + { -0.001157, 0, 0, 0}, + { 0.000743, 0, 0, 0}, + { 0.001570, 0, 0, 0}, + { -0.000115, 0, 0, 0}, + { -0.001218, 0, 0, 0}, + { 0.001831, 0, 0, 0}, + { 0.000023, 0, 0, 0}, + { -0.001922, 0, 0, 0}, + { 0.001739, 0, 0, 0}, + { -0.000712, 0, 0, 0}, + { 0.001555, 0, 0, 0}, + { -0.001708, 0, 0, 0}, + { 0.001233, 0, 0, 0}, + { 0.000207, 0, 0, 0}, + { 0.001049, 0, 0, 0}, + { -0.000728, 0, 0, 0}, + { -0.001631, 0, 0, 0}, + { -0.000314, 0, 0, 0}, + { 0.000483, 0, 0, 0}, + { -0.001800, 0, 0, 0}, + { 0.000942, 0, 0, 0}, + { -0.000345, 0, 0, 0}, + { 0.000697, 0, 0, 0}, + { -0.001019, 0, 0, 0}, + { -0.001570, 0, 0, 0}, + { -0.000023, 0, 0, 0}, + { -0.001279, 0, 0, 0}, + { 0.000804, 0, 0, 0}, + { -0.000896, 0, 0, 0}, + { -0.001432, 0, 0, 0}, + { 0.000605, 0, 0, 0}, + { -0.000084, 0, 0, 0}, + { 0.000911, 0, 0, 0}, + { 0.001953, 0, 0, 0}, + { -0.001402, 0, 0, 0}, + { -0.000636, 0, 0, 0}, + { 0.001509, 0, 0, 0}, + { -0.000820, 0, 0, 0}, + { 0.001248, 0, 0, 0}, + { 0.000253, 0, 0, 0}, + { 0.001524, 0, 0, 0}, + { 0.001126, 0, 0, 0}, + { 0.000360, 0, 0, 0}, + { -0.000391, 0, 0, 0}, + { 0.001907, 0, 0, 0}, + { 0.001386, 0, 0, 0}, + { -0.001111, 0, 0, 0}, + { 0.001616, 0, 0, 0}, + { -0.000881, 0, 0, 0}, + { 0.000146, 0, 0, 0}, + { 0.001080, 0, 0, 0}, + { -0.000054, 0, 0, 0}, + { 0.000283, 0, 0, 0}, + { -0.001693, 0, 0, 0}, + { -0.001264, 0, 0, 0}, + { -0.000513, 0, 0, 0}, + { -0.000161, 0, 0, 0}, + { -0.001877, 0, 0, 0}, + { -0.000835, 0, 0, 0}, + { 0.000636, 0, 0, 0}, + { 0.000008, 0, 0, 0}, + { -0.001907, 0, 0, 0}, + { -0.000222, 0, 0, 0}, + { 0.000375, 0, 0, 0}, + { -0.001739, 0, 0, 0}, + { -0.000406, 0, 0, 0}, + { -0.001233, 0, 0, 0}, + { 0.001708, 0, 0, 0}, + { -0.000942, 0, 0, 0}, + { 0.000820, 0, 0, 0}, + { 0.001846, 0, 0, 0}, + { 0.000467, 0, 0, 0} } +dcl_constantbuffer CB0[0:0][2], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 14 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +mad r0.zw, CB0[0][0].zzzw, l(0.000000, 0.000000, 0.500000, 0.500000), l(0.000000, 0.000000, -0.500000, -0.500000) +utof r1.xy, r0.xyxx +mad r0.zw, r1.xxxy, CB0[0][0].zzzw, r0.zzzw +round_ni r1.xy, r0.zwzz +add r0.zw, r0.zzzw, -r1.xxxy +ftoi r1.xy, r1.xyxx +iadd r2.xyzw, r1.xyxy, l(-1, 0, 0, -1) +mov r3.xy, r2.zwzz +mov r3.zw, l(0,0,0,0) +ld r3.xyz, r3.xyzw, T0[0].xyzw +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r4.xyz, r1.xyzw, T0[0].xyzw +iadd r5.xyzw, r1.xyxy, l(1, 0, 1, -1) +mov r6.xy, r5.zwzz +mov r6.zw, l(0,0,0,0) +ld r6.xyz, r6.xyzw, T0[0].xyzw +mov r5.zw, l(0,0,0,0) +ld r5.xyz, r5.xyzw, T0[0].xyzw +iadd r7.xyzw, r1.xyxy, l(-1, 1, 2, 0) +mov r8.xy, r7.zwzz +mov r8.zw, l(0,0,0,0) +ld r8.xyz, r8.xyzw, T0[0].xyzw +mov r7.zw, l(0,0,0,0) +ld r7.xyz, r7.xyzw, T0[0].xyzw +iadd r9.xyzw, r1.xyxy, l(0, 2, 0, 1) +mov r10.xy, r9.zwzz +mov r10.zw, l(0,0,0,0) +ld r10.xyz, r10.xyzw, T0[0].xyzw +mov r9.zw, l(0,0,0,0) +ld r9.xyz, r9.xyzw, T0[0].xyzw +iadd r11.xyzw, r1.xyxy, l(2, 1, 1, 1) +mov r12.xy, r11.zwzz +mov r12.zw, l(0,0,0,0) +ld r12.xyz, r12.xyzw, T0[0].xyzw +mov r11.zw, l(0,0,0,0) +ld r11.xyz, r11.xyzw, T0[0].xyzw +iadd r1.xy, r1.xyxx, l(1, 2, 0, 0) +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mul r3.xyz, r3.xyzx, r3.xyzx +mul r6.xyz, r6.xyzx, r6.xyzx +mul r2.xyz, r2.xyzx, r2.xyzx +mul r4.xyz, r4.xyzx, r4.xyzx +mul r5.xyz, r5.xyzx, r5.xyzx +mul r8.xyz, r8.xyzx, r8.xyzx +mul r7.xyz, r7.xyzx, r7.xyzx +mul r10.xyz, r10.xyzx, r10.xyzx +mul r12.xyz, r12.xyzx, r12.xyzx +mul r11.xyz, r11.xyzx, r11.xyzx +mul r9.xyz, r9.xyzx, r9.xyzx +mul r1.xyz, r1.xyzx, r1.xyzx +min r1.w, r2.y, r4.y +min r1.w, r1.w, r3.y +min r2.w, r5.y, r10.y +min r1.w, r1.w, r2.w +max r2.w, r2.y, r4.y +max r2.w, r2.w, r3.y +max r3.w, r5.y, r10.y +max r2.w, r2.w, r3.w +min r3.w, r4.y, r5.y +min r3.w, r3.w, r6.y +min r4.w, r8.y, r12.y +min r3.w, r3.w, r4.w +max r4.w, r4.y, r5.y +max r4.w, r4.w, r6.y +max r5.w, r8.y, r12.y +max r4.w, r4.w, r5.w +min r5.w, r7.y, r10.y +min r5.w, r4.y, r5.w +min r6.w, r9.y, r12.y +min r5.w, r5.w, r6.w +max r6.w, r7.y, r10.y +max r6.w, r4.y, r6.w +max r7.w, r9.y, r12.y +max r6.w, r6.w, r7.w +min r7.w, r10.y, r12.y +min r7.w, r5.y, r7.w +min r8.w, r1.y, r11.y +min r7.w, r7.w, r8.w +max r8.w, r10.y, r12.y +max r8.w, r5.y, r8.w +max r9.w, r1.y, r11.y +max r8.w, r8.w, r9.w +iadd r9.w, -r2.w, l(0x7ef07ebb) +iadd r10.w, -r4.w, l(0x7ef07ebb) +iadd r11.w, -r6.w, l(0x7ef07ebb) +iadd r12.w, -r8.w, l(0x7ef07ebb) +add r13.x, -r2.w, l(1.000000) +min r13.x, r1.w, r13.x +mul_sat r9.w, r9.w, r13.x +add r13.x, -r4.w, l(1.000000) +min r13.x, r3.w, r13.x +mul_sat r10.w, r10.w, r13.x +add r13.x, -r6.w, l(1.000000) +min r13.x, r5.w, r13.x +mul_sat r11.w, r11.w, r13.x +add r13.x, -r8.w, l(1.000000) +min r13.x, r7.w, r13.x +mul_sat r12.w, r12.w, r13.x +ushr r9.w, r9.w, l(1) +iadd r9.w, r9.w, l(0x1fbc4639) +ushr r10.w, r10.w, l(1) +iadd r10.w, r10.w, l(0x1fbc4639) +ushr r11.w, r11.w, l(1) +iadd r11.w, r11.w, l(0x1fbc4639) +ushr r12.w, r12.w, l(1) +iadd r12.w, r12.w, l(0x1fbc4639) +mul r9.w, r9.w, CB0[0][1].x +mul r10.w, r10.w, CB0[0][1].x +mul r11.w, r11.w, CB0[0][1].x +mul r12.w, r12.w, CB0[0][1].x +add r13.xy, -r0.wzww, l(1.000000, 1.000000, 0.000000, 0.000000) +mul r13.z, r13.x, r13.y +mul r13.xy, r0.zwzz, r13.xyxx +mul r0.z, r0.w, r0.z +add r0.w, -r1.w, r2.w +add r0.w, r0.w, l(0.031250) +iadd r0.w, -r0.w, l(0x7ef07ebb) +mul r1.w, r0.w, r13.z +add r2.w, -r3.w, r4.w +add r2.w, r2.w, l(0.031250) +iadd r2.w, -r2.w, l(0x7ef07ebb) +mul r3.w, r2.w, r13.x +add r4.w, -r5.w, r6.w +add r4.w, r4.w, l(0.031250) +iadd r4.w, -r4.w, l(0x7ef07ebb) +mul r5.w, r4.w, r13.y +add r6.w, -r7.w, r8.w +add r6.w, r6.w, l(0.031250) +iadd r6.w, -r6.w, l(0x7ef07ebb) +mul r7.w, r0.z, r6.w +mul r8.w, r1.w, r9.w +mul r13.w, r3.w, r10.w +mul r5.w, r5.w, r11.w +mad r3.w, r10.w, r3.w, r5.w +mad r0.w, r13.z, r0.w, r3.w +mul r7.w, r7.w, r12.w +mad r1.w, r9.w, r1.w, r7.w +mad r2.w, r13.x, r2.w, r1.w +mad r1.w, r13.y, r4.w, r1.w +mad r0.z, r0.z, r6.w, r3.w +add r3.w, r13.w, r13.w +mad r3.w, r8.w, l(2.000000), r3.w +mad r3.w, r5.w, l(2.000000), r3.w +mad r3.w, r7.w, l(2.000000), r3.w +add r3.w, r0.w, r3.w +add r3.w, r2.w, r3.w +add r3.w, r1.w, r3.w +add r3.w, r0.z, r3.w +iadd r4.w, -r3.w, l(0x7ef19fff) +mad r3.w, -r4.w, r3.w, l(2.000000) +mul r3.w, r3.w, r4.w +mul r2.xyz, r2.xyzx, r8.wwww +mad r2.xyz, r3.xyzx, r8.wwww, r2.xyzx +mad r2.xyz, r6.xyzx, r13.wwww, r2.xyzx +mad r2.xyz, r8.xyzx, r13.wwww, r2.xyzx +mad r2.xyz, r7.xyzx, r5.wwww, r2.xyzx +mad r2.xyz, r9.xyzx, r5.wwww, r2.xyzx +mad r2.xyz, r11.xyzx, r7.wwww, r2.xyzx +mad r1.xyz, r1.xyzx, r7.wwww, r2.xyzx +mad r1.xyz, r4.xyzx, r0.wwww, r1.xyzx +mad r1.xyz, r5.xyzx, r2.wwww, r1.xyzx +mad r1.xyz, r10.xyzx, r1.wwww, r1.xyzx +mad r1.xyz, r12.xyzx, r0.zzzz, r1.xyzx +mul_sat r1.xyz, r3.wwww, r1.xyzx +sqrt r1.xyz, r1.xyzx +bfi r0.y, l(4), l(4), r0.y, l(0) +bfi r0.x, l(4), l(0), r0.x, r0.y +add o0.xyz, r1.xyzx, icb[r0.x + 0].xxxx +mov o0.w, l(1.000000) +ret +// Approximately 175 instruction slots used +#endif + +const BYTE guest_output_ffx_cas_resample_dither_ps[] = +{ + 68, 88, 66, 67, 162, 124, + 243, 114, 220, 254, 28, 54, + 81, 63, 203, 49, 205, 242, + 53, 186, 1, 0, 0, 0, + 220, 40, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 120, 2, 0, 0, 172, 2, + 0, 0, 224, 2, 0, 0, + 64, 40, 0, 0, 82, 68, + 69, 70, 60, 2, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 20, 2, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 67, 97, 115, + 82, 101, 115, 97, 109, 112, + 108, 101, 67, 111, 110, 115, + 116, 97, 110, 116, 115, 0, + 171, 171, 151, 0, 0, 0, + 3, 0, 0, 0, 200, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 64, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 92, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 128, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 168, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 204, 1, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 240, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 99, + 97, 115, 95, 111, 117, 116, + 112, 117, 116, 95, 111, 102, + 102, 115, 101, 116, 0, 105, + 110, 116, 50, 0, 171, 171, + 1, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 1, 0, 0, + 120, 101, 95, 99, 97, 115, + 95, 105, 110, 112, 117, 116, + 95, 111, 117, 116, 112, 117, + 116, 95, 115, 105, 122, 101, + 95, 114, 97, 116, 105, 111, + 0, 102, 108, 111, 97, 116, + 50, 0, 171, 171, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 1, 0, 0, 120, 101, + 95, 99, 97, 115, 95, 115, + 104, 97, 114, 112, 110, 101, + 115, 115, 95, 112, 111, 115, + 116, 95, 115, 101, 116, 117, + 112, 0, 102, 108, 111, 97, + 116, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 3, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 88, 37, 0, 0, + 81, 0, 0, 0, 86, 9, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 2, 4, + 0, 0, 132, 131, 131, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 231, 230, 102, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 222, 221, + 221, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 204, 203, 203, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 168, 167, 167, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 159, 158, + 30, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 139, 139, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 182, 181, 181, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 178, 177, + 177, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 135, 134, 6, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 160, 159, 159, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 210, 209, + 209, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 155, 154, 26, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 149, 148, 148, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 146, 145, + 145, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 186, 185, 185, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 190, 189, 189, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 143, 142, + 14, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 137, 136, 8, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 158, 157, 157, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 228, + 228, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 138, 137, 137, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 163, 162, 34, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 253, 252, + 252, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 246, 245, 245, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 144, 143, 143, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 209, 208, + 208, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 139, 138, 10, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 188, 187, 187, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 254, 253, + 253, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 183, 182, 54, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 161, 160, 32, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 186, + 58, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 172, 171, 171, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 144, 143, 143, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 157, 156, + 156, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 230, 229, 229, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 220, 219, 219, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 194, 193, + 193, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 161, 160, 32, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 207, 206, 78, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 240, 239, + 239, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 157, 156, 156, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 130, 129, 129, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 154, 153, + 153, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 185, 184, 56, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 216, 215, 215, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 208, 207, + 207, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 181, 180, 180, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 244, 243, 243, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 232, 231, + 231, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 227, 226, 98, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 235, 234, 106, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 168, + 40, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 243, 242, 114, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 200, 199, 199, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 171, 170, + 42, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 170, 169, 169, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 211, 210, 82, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 192, 191, + 191, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 236, 235, 235, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 223, 222, 94, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 223, 222, + 94, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 237, 236, 236, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 140, 139, 139, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 153, 152, + 24, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 249, 248, 120, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 186, 185, 185, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 155, 154, + 26, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 201, 200, 72, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 210, 209, 209, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 134, 133, + 133, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 213, 212, 212, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 217, 216, 88, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 208, 207, + 207, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 171, 170, 42, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 145, 144, 144, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 221, 220, + 220, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 216, 215, 215, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 180, 179, 179, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 243, 242, + 114, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 175, 174, 46, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 156, 155, 155, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 190, 189, + 189, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 151, 150, 22, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 248, 247, 247, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 199, 198, + 70, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 170, 169, 169, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 252, 251, 251, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 218, 217, + 217, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 136, 135, 135, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 131, 130, 2, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 244, 243, + 243, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 158, 157, 157, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 173, 172, 172, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 180, 179, + 179, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 214, 213, 213, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 242, 241, 241, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 191, 190, + 62, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 239, 238, 110, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 238, 237, 237, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 149, + 149, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 197, 196, 196, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 209, 208, 208, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 195, 194, + 66, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 154, 153, 153, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 145, 144, 144, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 196, 195, + 195, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 254, 126, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 251, 250, 122, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 254, 253, + 253, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 139, 138, 10, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 225, 224, 96, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 163, + 163, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 141, 140, 140, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 202, 201, 201, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 129, 128, + 0, 183, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 165, 164, 164, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 176, 175, 175, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 230, 229, + 229, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 131, 130, 2, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 156, 155, 155, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 203, 202, + 74, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 176, 175, 175, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 141, 140, 140, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 194, 193, + 193, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 137, 136, 8, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 203, 202, 74, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 172, 171, + 171, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 205, 204, 204, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 251, 250, 122, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 245, 244, + 244, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 202, 201, 201, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 135, 135, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 179, 178, + 50, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 220, 219, 219, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 132, 131, 131, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 221, 220, + 220, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 234, 233, 233, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 249, 248, 120, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 163, 162, + 34, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 218, 217, 217, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 219, 218, 90, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 226, 225, + 225, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 142, 141, 141, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 231, 231, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 207, 206, + 78, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 234, 233, 233, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 179, 178, 50, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 130, 129, + 129, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 174, 173, 173, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 185, 184, 56, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 198, 197, + 197, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 173, 172, 172, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 187, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 175, 174, + 46, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 212, 211, 211, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 152, 151, 151, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 236, + 236, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 229, 228, 228, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 201, 200, 72, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 196, 195, + 195, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 150, 149, 149, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 177, 176, 176, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 248, 247, + 247, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 184, 183, 183, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 147, 146, 18, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 241, 240, + 240, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 166, 165, 165, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 151, 150, 22, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 254, + 126, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 174, 173, 173, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 233, 232, 104, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 199, 198, + 70, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 178, 177, 177, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 192, 191, 191, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 227, 226, + 98, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 189, 188, 188, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 143, 142, 14, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 148, 147, + 147, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 133, 132, 132, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 147, 146, 18, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 237, + 237, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 226, 225, 225, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 152, 151, 151, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 195, 194, + 66, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 206, 205, 205, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 241, 240, 240, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 160, 159, + 159, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 240, 239, 239, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 193, 192, 192, 55, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 252, 251, + 251, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 228, 227, 227, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 187, 186, 58, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 203, + 203, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 224, 223, 223, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 162, 161, 161, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 217, 216, + 88, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 138, 137, 137, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 191, 190, 62, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 213, + 213, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 165, 164, 164, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 253, 252, 252, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 235, + 235, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 247, 246, 118, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 181, 180, 180, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 183, 182, + 54, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 134, 133, 133, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 206, 205, 205, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 193, 192, + 192, 183, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 168, 167, 167, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 211, 210, 82, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 235, 234, + 106, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 188, 187, 187, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 158, 30, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 177, 176, + 176, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 239, 238, 110, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 59, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 184, 183, + 183, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 167, 166, 38, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 198, 197, 197, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 215, 214, + 86, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 164, 163, 163, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 133, 132, 132, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 200, 199, + 199, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 148, 147, 147, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 189, 188, 188, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 205, 204, + 204, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 250, 249, 249, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 182, 181, 181, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 146, 145, + 145, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 212, 211, 211, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 231, 230, 102, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 153, 152, + 24, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 142, 141, 141, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 225, 224, 96, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 149, 148, + 148, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 222, 221, 221, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 166, 165, 165, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 134, + 6, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 169, 168, 40, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 246, 245, 245, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 219, 218, + 90, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 167, 166, 38, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 129, 128, 0, 55, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 250, 249, + 249, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 233, 232, 104, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 197, 196, 196, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 228, 227, + 227, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 213, 212, 212, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 162, 161, 161, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 224, 223, + 223, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 247, 246, 118, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 215, 214, 86, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 241, + 241, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 245, 244, 244, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 100, 32, 0, 4, + 50, 16, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 14, 0, + 0, 0, 27, 0, 0, 5, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 128, 48, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 17, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 191, + 0, 0, 0, 191, 86, 0, + 0, 5, 50, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 1, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 166, 14, 16, 0, 0, 0, + 0, 0, 65, 0, 0, 5, + 50, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 14, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 27, 0, 0, 5, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 50, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 50, 0, + 16, 0, 6, 0, 0, 0, + 230, 10, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 4, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 0, 16, 0, 8, 0, + 0, 0, 230, 10, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 4, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 10, 0, 0, 0, 230, 10, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 11, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 12, 0, 0, 0, + 230, 10, 16, 0, 11, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 12, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 12, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 12, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 30, 0, + 0, 8, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 187, 126, 240, 126, + 30, 0, 0, 8, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 30, 0, 0, 8, + 130, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 0, 0, + 0, 8, 18, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 51, 0, 0, 7, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 13, 0, 0, 0, 56, 32, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 0, 0, 0, 8, + 18, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 51, 0, + 0, 7, 18, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 56, 32, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 51, 0, 0, 7, + 18, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 56, 32, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 10, 0, 16, 0, + 13, 0, 0, 0, 0, 0, + 0, 8, 18, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 51, 0, 0, 7, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 13, 0, 0, 0, 56, 32, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 57, 70, 188, 31, 85, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 57, 70, 188, 31, + 85, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 57, 70, + 188, 31, 85, 0, 0, 7, + 130, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 12, 0, 0, 0, + 58, 0, 16, 0, 12, 0, + 0, 0, 1, 64, 0, 0, + 57, 70, 188, 31, 56, 0, + 0, 9, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 11, 50, 0, 16, 0, + 13, 0, 0, 0, 182, 15, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 66, 0, + 16, 0, 13, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 26, 0, 16, 0, + 13, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 13, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 13, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 13, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 0, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 255, 159, + 241, 126, 50, 0, 0, 10, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 56, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 8, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 246, 15, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 246, 15, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 246, 15, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 56, 32, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 75, 0, 0, 5, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 140, 0, 0, 11, + 34, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 140, 0, + 0, 11, 18, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 6, 144, 144, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 175, 0, + 0, 0, 14, 0, 0, 0, + 0, 1, 0, 0, 2, 0, + 0, 0, 115, 0, 0, 0, + 20, 0, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h new file mode 100644 index 000000000..1a7634fd6 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h @@ -0,0 +1,1264 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeCasResampleConstants +// { +// +// int2 xe_cas_output_offset; // Offset: 0 Size: 8 +// float2 xe_cas_input_output_size_ratio;// Offset: 8 Size: 8 +// float xe_cas_sharpness_post_setup; // Offset: 16 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeCasResampleConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][2], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 14 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +mad r0.zw, CB0[0][0].zzzw, l(0.000000, 0.000000, 0.500000, 0.500000), l(0.000000, 0.000000, -0.500000, -0.500000) +utof r0.xy, r0.xyxx +mad r0.xy, r0.xyxx, CB0[0][0].zwzz, r0.zwzz +round_ni r0.zw, r0.xxxy +add r0.xy, -r0.zwzz, r0.xyxx +ftoi r1.xy, r0.zwzz +iadd r2.xyzw, r1.xyxy, l(-1, 0, 0, -1) +mov r3.xy, r2.zwzz +mov r3.zw, l(0,0,0,0) +ld r3.xyz, r3.xyzw, T0[0].xyzw +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r4.xyz, r1.xyzw, T0[0].xyzw +iadd r5.xyzw, r1.xyxy, l(1, 0, 1, -1) +mov r6.xy, r5.zwzz +mov r6.zw, l(0,0,0,0) +ld r6.xyz, r6.xyzw, T0[0].xyzw +mov r5.zw, l(0,0,0,0) +ld r5.xyz, r5.xyzw, T0[0].xyzw +iadd r7.xyzw, r1.xyxy, l(-1, 1, 2, 0) +mov r8.xy, r7.zwzz +mov r8.zw, l(0,0,0,0) +ld r8.xyz, r8.xyzw, T0[0].xyzw +mov r7.zw, l(0,0,0,0) +ld r7.xyz, r7.xyzw, T0[0].xyzw +iadd r9.xyzw, r1.xyxy, l(0, 2, 0, 1) +mov r10.xy, r9.zwzz +mov r10.zw, l(0,0,0,0) +ld r10.xyz, r10.xyzw, T0[0].xyzw +mov r9.zw, l(0,0,0,0) +ld r9.xyz, r9.xyzw, T0[0].xyzw +iadd r11.xyzw, r1.xyxy, l(2, 1, 1, 1) +mov r12.xy, r11.zwzz +mov r12.zw, l(0,0,0,0) +ld r12.xyz, r12.xyzw, T0[0].xyzw +mov r11.zw, l(0,0,0,0) +ld r11.xyz, r11.xyzw, T0[0].xyzw +iadd r1.xy, r1.xyxx, l(1, 2, 0, 0) +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mul r3.xyz, r3.xyzx, r3.xyzx +mul r6.xyz, r6.xyzx, r6.xyzx +mul r2.xyz, r2.xyzx, r2.xyzx +mul r4.xyz, r4.xyzx, r4.xyzx +mul r5.xyz, r5.xyzx, r5.xyzx +mul r8.xyz, r8.xyzx, r8.xyzx +mul r7.xyz, r7.xyzx, r7.xyzx +mul r10.xyz, r10.xyzx, r10.xyzx +mul r12.xyz, r12.xyzx, r12.xyzx +mul r11.xyz, r11.xyzx, r11.xyzx +mul r9.xyz, r9.xyzx, r9.xyzx +mul r1.xyz, r1.xyzx, r1.xyzx +min r0.z, r2.y, r4.y +min r0.z, r0.z, r3.y +min r0.w, r5.y, r10.y +min r0.z, r0.w, r0.z +max r0.w, r2.y, r4.y +max r0.w, r0.w, r3.y +max r1.w, r5.y, r10.y +max r0.w, r0.w, r1.w +min r1.w, r4.y, r5.y +min r1.w, r1.w, r6.y +min r2.w, r8.y, r12.y +min r1.w, r1.w, r2.w +max r2.w, r4.y, r5.y +max r2.w, r2.w, r6.y +max r3.w, r8.y, r12.y +max r2.w, r2.w, r3.w +min r3.w, r7.y, r10.y +min r3.w, r3.w, r4.y +min r4.w, r9.y, r12.y +min r3.w, r3.w, r4.w +max r4.w, r7.y, r10.y +max r4.w, r4.w, r4.y +max r5.w, r9.y, r12.y +max r4.w, r4.w, r5.w +min r5.w, r10.y, r12.y +min r5.w, r5.w, r5.y +min r6.w, r1.y, r11.y +min r5.w, r5.w, r6.w +max r6.w, r10.y, r12.y +max r6.w, r5.y, r6.w +max r7.w, r1.y, r11.y +max r6.w, r6.w, r7.w +iadd r7.w, -r0.w, l(0x7ef07ebb) +iadd r8.w, -r2.w, l(0x7ef07ebb) +iadd r9.w, -r4.w, l(0x7ef07ebb) +iadd r10.w, -r6.w, l(0x7ef07ebb) +add r11.w, -r0.w, l(1.000000) +min r11.w, r0.z, r11.w +mul_sat r7.w, r7.w, r11.w +add r11.w, -r2.w, l(1.000000) +min r11.w, r1.w, r11.w +mul_sat r8.w, r8.w, r11.w +add r11.w, -r4.w, l(1.000000) +min r11.w, r3.w, r11.w +mul_sat r9.w, r9.w, r11.w +add r11.w, -r6.w, l(1.000000) +min r11.w, r5.w, r11.w +mul_sat r10.w, r10.w, r11.w +ushr r7.w, r7.w, l(1) +iadd r7.w, r7.w, l(0x1fbc4639) +ushr r8.w, r8.w, l(1) +iadd r8.w, r8.w, l(0x1fbc4639) +ushr r9.w, r9.w, l(1) +iadd r9.w, r9.w, l(0x1fbc4639) +ushr r10.w, r10.w, l(1) +iadd r10.w, r10.w, l(0x1fbc4639) +mul r7.w, r7.w, CB0[0][1].x +mul r8.w, r8.w, CB0[0][1].x +mul r9.w, r9.w, CB0[0][1].x +mul r10.w, r10.w, CB0[0][1].x +add r13.xy, -r0.yxyy, l(1.000000, 1.000000, 0.000000, 0.000000) +mul r11.w, r13.x, r13.y +mul r13.xy, r0.xyxx, r13.xyxx +mul r0.x, r0.y, r0.x +add r0.y, -r0.z, r0.w +add r0.y, r0.y, l(0.031250) +iadd r0.y, -r0.y, l(0x7ef07ebb) +mul r0.z, r0.y, r11.w +add r0.w, -r1.w, r2.w +add r0.w, r0.w, l(0.031250) +iadd r0.w, -r0.w, l(0x7ef07ebb) +mul r1.w, r0.w, r13.x +add r2.w, -r3.w, r4.w +add r2.w, r2.w, l(0.031250) +iadd r2.w, -r2.w, l(0x7ef07ebb) +mul r3.w, r2.w, r13.y +add r4.w, -r5.w, r6.w +add r4.w, r4.w, l(0.031250) +iadd r4.w, -r4.w, l(0x7ef07ebb) +mul r5.w, r0.x, r4.w +mul r6.w, r0.z, r7.w +mul r12.w, r1.w, r8.w +mul r3.w, r3.w, r9.w +mad r1.w, r8.w, r1.w, r3.w +mad r0.y, r11.w, r0.y, r1.w +mul r5.w, r5.w, r10.w +mad r0.z, r7.w, r0.z, r5.w +mad r0.w, r13.x, r0.w, r0.z +mad r0.z, r13.y, r2.w, r0.z +mad r0.x, r0.x, r4.w, r1.w +add r1.w, r12.w, r12.w +mad r1.w, r6.w, l(2.000000), r1.w +mad r1.w, r3.w, l(2.000000), r1.w +mad r1.w, r5.w, l(2.000000), r1.w +add r1.w, r0.y, r1.w +add r1.w, r0.w, r1.w +add r1.w, r0.z, r1.w +add r1.w, r0.x, r1.w +iadd r2.w, -r1.w, l(0x7ef19fff) +mad r1.w, -r2.w, r1.w, l(2.000000) +mul r1.w, r1.w, r2.w +mul r2.xyz, r2.xyzx, r6.wwww +mad r2.xyz, r3.xyzx, r6.wwww, r2.xyzx +mad r2.xyz, r6.xyzx, r12.wwww, r2.xyzx +mad r2.xyz, r8.xyzx, r12.wwww, r2.xyzx +mad r2.xyz, r7.xyzx, r3.wwww, r2.xyzx +mad r2.xyz, r9.xyzx, r3.wwww, r2.xyzx +mad r2.xyz, r11.xyzx, r5.wwww, r2.xyzx +mad r1.xyz, r1.xyzx, r5.wwww, r2.xyzx +mad r1.xyz, r4.xyzx, r0.yyyy, r1.xyzx +mad r1.xyz, r5.xyzx, r0.wwww, r1.xyzx +mad r0.yzw, r10.xxyz, r0.zzzz, r1.xxyz +mad r0.xyz, r12.xyzx, r0.xxxx, r0.yzwy +mul_sat r0.xyz, r1.wwww, r0.xyzx +sqrt o0.xyz, r0.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 172 instruction slots used +#endif + +const BYTE guest_output_ffx_cas_resample_ps[] = +{ + 68, 88, 66, 67, 153, 223, + 100, 209, 57, 228, 221, 164, + 114, 23, 52, 94, 29, 110, + 188, 4, 1, 0, 0, 0, + 92, 24, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 120, 2, 0, 0, 172, 2, + 0, 0, 224, 2, 0, 0, + 192, 23, 0, 0, 82, 68, + 69, 70, 60, 2, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 20, 2, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 67, 97, 115, + 82, 101, 115, 97, 109, 112, + 108, 101, 67, 111, 110, 115, + 116, 97, 110, 116, 115, 0, + 171, 171, 151, 0, 0, 0, + 3, 0, 0, 0, 200, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 64, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 92, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 128, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 168, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 204, 1, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 240, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 99, + 97, 115, 95, 111, 117, 116, + 112, 117, 116, 95, 111, 102, + 102, 115, 101, 116, 0, 105, + 110, 116, 50, 0, 171, 171, + 1, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 1, 0, 0, + 120, 101, 95, 99, 97, 115, + 95, 105, 110, 112, 117, 116, + 95, 111, 117, 116, 112, 117, + 116, 95, 115, 105, 122, 101, + 95, 114, 97, 116, 105, 111, + 0, 102, 108, 111, 97, 116, + 50, 0, 171, 171, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 1, 0, 0, 120, 101, + 95, 99, 97, 115, 95, 115, + 104, 97, 114, 112, 110, 101, + 115, 115, 95, 112, 111, 115, + 116, 95, 115, 101, 116, 117, + 112, 0, 102, 108, 111, 97, + 116, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 3, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 216, 20, 0, 0, + 81, 0, 0, 0, 54, 5, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 100, 32, 0, 4, + 50, 16, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 14, 0, + 0, 0, 27, 0, 0, 5, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 128, 48, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 17, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 191, + 0, 0, 0, 191, 86, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 230, 138, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 65, 0, 0, 5, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 50, 0, 16, 0, + 0, 0, 0, 0, 230, 10, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 27, 0, 0, 5, 50, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 50, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 50, 0, + 16, 0, 6, 0, 0, 0, + 230, 10, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 4, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 0, 16, 0, 8, 0, + 0, 0, 230, 10, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 4, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 10, 0, 0, 0, 230, 10, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 11, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 12, 0, 0, 0, + 230, 10, 16, 0, 11, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 12, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 12, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 12, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 30, 0, + 0, 8, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 187, 126, 240, 126, + 30, 0, 0, 8, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 30, 0, 0, 8, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 0, 0, + 0, 8, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 51, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 56, 32, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 0, 0, 0, 8, + 130, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 51, 0, + 0, 7, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 56, 32, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 51, 0, 0, 7, + 130, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 56, 32, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 0, 0, + 0, 8, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 51, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 56, 32, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 57, 70, 188, 31, 85, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 57, 70, 188, 31, + 85, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 57, 70, + 188, 31, 85, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 57, 70, 188, 31, 56, 0, + 0, 9, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 11, 50, 0, 16, 0, + 13, 0, 0, 0, 22, 5, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 26, 0, 16, 0, + 13, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 13, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 13, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 58, 0, 16, 0, 12, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 1, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 0, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 255, 159, + 241, 126, 50, 0, 0, 10, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 56, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 6, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 246, 15, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 246, 15, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 246, 15, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 246, 15, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 226, 0, 16, 0, 0, 0, + 0, 0, 6, 9, 16, 0, + 10, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 6, 9, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 150, 7, 16, 0, 0, 0, + 0, 0, 56, 32, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 75, 0, 0, 5, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 172, 0, + 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 114, 0, 0, 0, + 20, 0, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h new file mode 100644 index 000000000..14e7dd87b --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h @@ -0,0 +1,1454 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeCasSharpenConstants +// { +// +// int2 xe_cas_output_offset; // Offset: 0 Size: 8 +// float xe_cas_sharpness_post_setup; // Offset: 8 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeCasSharpenConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.001003, 0, 0, 0}, + { 0.000881, 0, 0, 0}, + { 0.001693, 0, 0, 0}, + { -0.001555, 0, 0, 0}, + { 0.001279, 0, 0, 0}, + { -0.000605, 0, 0, 0}, + { 0.001065, 0, 0, 0}, + { -0.001386, 0, 0, 0}, + { 0.001356, 0, 0, 0}, + { 0.000513, 0, 0, 0}, + { 0.001218, 0, 0, 0}, + { -0.001601, 0, 0, 0}, + { 0.000590, 0, 0, 0}, + { -0.000283, 0, 0, 0}, + { 0.001111, 0, 0, 0}, + { -0.001417, 0, 0, 0}, + { 0.001448, 0, 0, 0}, + { -0.000544, 0, 0, 0}, + { 0.000130, 0, 0, 0}, + { -0.001203, 0, 0, 0}, + { 0.000437, 0, 0, 0}, + { -0.001049, 0, 0, 0}, + { 0.000620, 0, 0, 0}, + { -0.000483, 0, 0, 0}, + { 0.001877, 0, 0, 0}, + { -0.001095, 0, 0, 0}, + { -0.000100, 0, 0, 0}, + { -0.000528, 0, 0, 0}, + { 0.001432, 0, 0, 0}, + { -0.001938, 0, 0, 0}, + { -0.000697, 0, 0, 0}, + { 0.000038, 0, 0, 0}, + { 0.000712, 0, 0, 0}, + { -0.001310, 0, 0, 0}, + { 0.001095, 0, 0, 0}, + { -0.000299, 0, 0, 0}, + { 0.001754, 0, 0, 0}, + { -0.001677, 0, 0, 0}, + { 0.001478, 0, 0, 0}, + { -0.000038, 0, 0, 0}, + { 0.000789, 0, 0, 0}, + { -0.001831, 0, 0, 0}, + { 0.000299, 0, 0, 0}, + { 0.000988, 0, 0, 0}, + { -0.001172, 0, 0, 0}, + { 0.000176, 0, 0, 0}, + { 0.001647, 0, 0, 0}, + { -0.001585, 0, 0, 0}, + { 0.000345, 0, 0, 0}, + { 0.001861, 0, 0, 0}, + { -0.001769, 0, 0, 0}, + { -0.000866, 0, 0, 0}, + { 0.000896, 0, 0, 0}, + { 0.000161, 0, 0, 0}, + { -0.000927, 0, 0, 0}, + { -0.001524, 0, 0, 0}, + { -0.000651, 0, 0, 0}, + { 0.001294, 0, 0, 0}, + { -0.000804, 0, 0, 0}, + { -0.001463, 0, 0, 0}, + { 0.001800, 0, 0, 0}, + { -0.000850, 0, 0, 0}, + { 0.000850, 0, 0, 0}, + { -0.000452, 0, 0, 0}, + { -0.001065, 0, 0, 0}, + { -0.000146, 0, 0, 0}, + { 0.000237, 0, 0, 0}, + { 0.001417, 0, 0, 0}, + { -0.000590, 0, 0, 0}, + { -0.000191, 0, 0, 0}, + { 0.001601, 0, 0, 0}, + { 0.001019, 0, 0, 0}, + { 0.000406, 0, 0, 0}, + { -0.000207, 0, 0, 0}, + { 0.001585, 0, 0, 0}, + { 0.000651, 0, 0, 0}, + { -0.000069, 0, 0, 0}, + { 0.000421, 0, 0, 0}, + { -0.001647, 0, 0, 0}, + { 0.001371, 0, 0, 0}, + { 0.000927, 0, 0, 0}, + { -0.000666, 0, 0, 0}, + { 0.001187, 0, 0, 0}, + { -0.001448, 0, 0, 0}, + { 0.000574, 0, 0, 0}, + { -0.001892, 0, 0, 0}, + { 0.000758, 0, 0, 0}, + { -0.001294, 0, 0, 0}, + { 0.001922, 0, 0, 0}, + { -0.001662, 0, 0, 0}, + { -0.001034, 0, 0, 0}, + { -0.000498, 0, 0, 0}, + { -0.001861, 0, 0, 0}, + { 0.001203, 0, 0, 0}, + { -0.000329, 0, 0, 0}, + { -0.001371, 0, 0, 0}, + { 0.001631, 0, 0, 0}, + { -0.001846, 0, 0, 0}, + { 0.000728, 0, 0, 0}, + { -0.000911, 0, 0, 0}, + { 0.001815, 0, 0, 0}, + { -0.001141, 0, 0, 0}, + { -0.000375, 0, 0, 0}, + { 0.000100, 0, 0, 0}, + { -0.000743, 0, 0, 0}, + { 0.001172, 0, 0, 0}, + { 0.000069, 0, 0, 0}, + { 0.001494, 0, 0, 0}, + { 0.000973, 0, 0, 0}, + { -0.000957, 0, 0, 0}, + { 0.001938, 0, 0, 0}, + { 0.000528, 0, 0, 0}, + { 0.000054, 0, 0, 0}, + { -0.001248, 0, 0, 0}, + { -0.000268, 0, 0, 0}, + { 0.001540, 0, 0, 0}, + { -0.000008, 0, 0, 0}, + { 0.000314, 0, 0, 0}, + { 0.001340, 0, 0, 0}, + { -0.001754, 0, 0, 0}, + { 0.000498, 0, 0, 0}, + { -0.001187, 0, 0, 0}, + { 0.000774, 0, 0, 0}, + { -0.001340, 0, 0, 0}, + { 0.000268, 0, 0, 0}, + { -0.001478, 0, 0, 0}, + { -0.000130, 0, 0, 0}, + { -0.000774, 0, 0, 0}, + { 0.001310, 0, 0, 0}, + { 0.000391, 0, 0, 0}, + { 0.000957, 0, 0, 0}, + { -0.000467, 0, 0, 0}, + { -0.001540, 0, 0, 0}, + { 0.001034, 0, 0, 0}, + { -0.000682, 0, 0, 0}, + { 0.001677, 0, 0, 0}, + { 0.001003, 0, 0, 0}, + { -0.000421, 0, 0, 0}, + { 0.001785, 0, 0, 0}, + { -0.000237, 0, 0, 0}, + { -0.000620, 0, 0, 0}, + { 0.001662, 0, 0, 0}, + { 0.000835, 0, 0, 0}, + { -0.001723, 0, 0, 0}, + { -0.001080, 0, 0, 0}, + { 0.001769, 0, 0, 0}, + { -0.000789, 0, 0, 0}, + { -0.001785, 0, 0, 0}, + { 0.000682, 0, 0, 0}, + { -0.000988, 0, 0, 0}, + { -0.001325, 0, 0, 0}, + { -0.000176, 0, 0, 0}, + { -0.001509, 0, 0, 0}, + { 0.000329, 0, 0, 0}, + { -0.001953, 0, 0, 0}, + { 0.000666, 0, 0, 0}, + { -0.001616, 0, 0, 0}, + { 0.001157, 0, 0, 0}, + { 0.000452, 0, 0, 0}, + { -0.000437, 0, 0, 0}, + { 0.000191, 0, 0, 0}, + { -0.001494, 0, 0, 0}, + { 0.001141, 0, 0, 0}, + { 0.000084, 0, 0, 0}, + { 0.001892, 0, 0, 0}, + { 0.001402, 0, 0, 0}, + { 0.000559, 0, 0, 0}, + { 0.000115, 0, 0, 0}, + { 0.001264, 0, 0, 0}, + { -0.000574, 0, 0, 0}, + { -0.000973, 0, 0, 0}, + { 0.001325, 0, 0, 0}, + { 0.000222, 0, 0, 0}, + { -0.000758, 0, 0, 0}, + { -0.001356, 0, 0, 0}, + { 0.001463, 0, 0, 0}, + { 0.000866, 0, 0, 0}, + { -0.000360, 0, 0, 0}, + { 0.000544, 0, 0, 0}, + { -0.001126, 0, 0, 0}, + { -0.000253, 0, 0, 0}, + { -0.000559, 0, 0, 0}, + { -0.001815, 0, 0, 0}, + { 0.001723, 0, 0, 0}, + { -0.001157, 0, 0, 0}, + { 0.000743, 0, 0, 0}, + { 0.001570, 0, 0, 0}, + { -0.000115, 0, 0, 0}, + { -0.001218, 0, 0, 0}, + { 0.001831, 0, 0, 0}, + { 0.000023, 0, 0, 0}, + { -0.001922, 0, 0, 0}, + { 0.001739, 0, 0, 0}, + { -0.000712, 0, 0, 0}, + { 0.001555, 0, 0, 0}, + { -0.001708, 0, 0, 0}, + { 0.001233, 0, 0, 0}, + { 0.000207, 0, 0, 0}, + { 0.001049, 0, 0, 0}, + { -0.000728, 0, 0, 0}, + { -0.001631, 0, 0, 0}, + { -0.000314, 0, 0, 0}, + { 0.000483, 0, 0, 0}, + { -0.001800, 0, 0, 0}, + { 0.000942, 0, 0, 0}, + { -0.000345, 0, 0, 0}, + { 0.000697, 0, 0, 0}, + { -0.001019, 0, 0, 0}, + { -0.001570, 0, 0, 0}, + { -0.000023, 0, 0, 0}, + { -0.001279, 0, 0, 0}, + { 0.000804, 0, 0, 0}, + { -0.000896, 0, 0, 0}, + { -0.001432, 0, 0, 0}, + { 0.000605, 0, 0, 0}, + { -0.000084, 0, 0, 0}, + { 0.000911, 0, 0, 0}, + { 0.001953, 0, 0, 0}, + { -0.001402, 0, 0, 0}, + { -0.000636, 0, 0, 0}, + { 0.001509, 0, 0, 0}, + { -0.000820, 0, 0, 0}, + { 0.001248, 0, 0, 0}, + { 0.000253, 0, 0, 0}, + { 0.001524, 0, 0, 0}, + { 0.001126, 0, 0, 0}, + { 0.000360, 0, 0, 0}, + { -0.000391, 0, 0, 0}, + { 0.001907, 0, 0, 0}, + { 0.001386, 0, 0, 0}, + { -0.001111, 0, 0, 0}, + { 0.001616, 0, 0, 0}, + { -0.000881, 0, 0, 0}, + { 0.000146, 0, 0, 0}, + { 0.001080, 0, 0, 0}, + { -0.000054, 0, 0, 0}, + { 0.000283, 0, 0, 0}, + { -0.001693, 0, 0, 0}, + { -0.001264, 0, 0, 0}, + { -0.000513, 0, 0, 0}, + { -0.000161, 0, 0, 0}, + { -0.001877, 0, 0, 0}, + { -0.000835, 0, 0, 0}, + { 0.000636, 0, 0, 0}, + { 0.000008, 0, 0, 0}, + { -0.001907, 0, 0, 0}, + { -0.000222, 0, 0, 0}, + { 0.000375, 0, 0, 0}, + { -0.001739, 0, 0, 0}, + { -0.000406, 0, 0, 0}, + { -0.001233, 0, 0, 0}, + { 0.001708, 0, 0, 0}, + { -0.000942, 0, 0, 0}, + { 0.000820, 0, 0, 0}, + { 0.001846, 0, 0, 0}, + { 0.000467, 0, 0, 0} } +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 6 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +iadd r1.xyzw, r0.xyxy, l(-1, 0, 0, -1) +mov r2.xy, r1.zwzz +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r3.xyz, r0.xyzw, T0[0].xyzw +iadd r4.xyzw, r0.xyxy, l(0, 1, 1, 0) +mov r5.xy, r4.zwzz +mov r5.zw, l(0,0,0,0) +ld r5.xyz, r5.xyzw, T0[0].xyzw +mov r4.zw, l(0,0,0,0) +ld r4.xyz, r4.xyzw, T0[0].xyzw +mul r2.xyz, r2.xyzx, r2.xyzx +mul r1.xyz, r1.xyzx, r1.xyzx +mul r0.z, r3.y, r3.y +mul r5.xyz, r5.xyzx, r5.xyzx +mul r4.xyz, r4.xyzx, r4.xyzx +min r0.w, r0.z, r5.y +min r0.w, r0.w, r1.y +min r1.w, r2.y, r4.y +min r0.w, r0.w, r1.w +max r0.z, r0.z, r5.y +max r0.z, r0.z, r1.y +max r1.w, r2.y, r4.y +max r0.z, r0.z, r1.w +iadd r1.w, -r0.z, l(0x7ef07ebb) +add r0.z, -r0.z, l(1.000000) +min r0.z, r0.z, r0.w +mul_sat r0.z, r1.w, r0.z +ushr r0.z, r0.z, l(1) +iadd r0.z, r0.z, l(0x1fbc4639) +mul r0.z, r0.z, CB0[0][0].z +mad r0.w, r0.z, l(4.000000), l(1.000000) +iadd r1.w, -r0.w, l(0x7ef19fff) +mad r0.w, -r1.w, r0.w, l(2.000000) +mul r0.w, r0.w, r1.w +mul r1.xyz, r0.zzzz, r1.xyzx +mad r1.xyz, r2.xyzx, r0.zzzz, r1.xyzx +mad r1.xyz, r5.xyzx, r0.zzzz, r1.xyzx +mad r1.xyz, r4.xyzx, r0.zzzz, r1.xyzx +mad r1.xyz, r3.xyzx, r3.xyzx, r1.xyzx +mul_sat r1.xyz, r0.wwww, r1.xyzx +sqrt r1.xyz, r1.xyzx +bfi r0.y, l(4), l(4), r0.y, l(0) +bfi r0.x, l(4), l(0), r0.x, r0.y +add o0.xyz, r1.xyzx, icb[r0.x + 0].xxxx +mov o0.w, l(1.000000) +ret +// Approximately 52 instruction slots used +#endif + +const BYTE guest_output_ffx_cas_sharpen_dither_ps[] = +{ + 68, 88, 66, 67, 200, 82, + 48, 235, 252, 11, 120, 26, + 79, 183, 112, 246, 236, 81, + 181, 118, 1, 0, 0, 0, + 168, 25, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 4, 2, 0, 0, 56, 2, + 0, 0, 108, 2, 0, 0, + 12, 25, 0, 0, 82, 68, + 69, 70, 200, 1, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 160, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 67, 97, 115, + 83, 104, 97, 114, 112, 101, + 110, 67, 111, 110, 115, 116, + 97, 110, 116, 115, 0, 171, + 171, 171, 151, 0, 0, 0, + 2, 0, 0, 0, 200, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 24, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 52, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 88, 1, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 124, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 120, 101, + 95, 99, 97, 115, 95, 111, + 117, 116, 112, 117, 116, 95, + 111, 102, 102, 115, 101, 116, + 0, 105, 110, 116, 50, 0, + 171, 171, 1, 0, 2, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 1, + 0, 0, 120, 101, 95, 99, + 97, 115, 95, 115, 104, 97, + 114, 112, 110, 101, 115, 115, + 95, 112, 111, 115, 116, 95, + 115, 101, 116, 117, 112, 0, + 102, 108, 111, 97, 116, 0, + 171, 171, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 116, 1, + 0, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 49, 0, + 73, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171, 83, 72, 69, 88, + 152, 22, 0, 0, 81, 0, + 0, 0, 166, 5, 0, 0, + 106, 8, 0, 1, 53, 24, + 0, 0, 2, 4, 0, 0, + 132, 131, 131, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 231, 230, + 102, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 222, 221, 221, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 204, 203, 203, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 168, 167, + 167, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 159, 158, 30, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 140, 139, 139, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 182, 181, + 181, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 178, 177, 177, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 135, 134, 6, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 160, 159, + 159, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 210, 209, 209, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 155, 154, 26, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 149, 148, + 148, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 146, 145, 145, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 186, 185, 185, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 190, 189, + 189, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 143, 142, 14, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 137, 136, 8, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 158, 157, + 157, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 229, 228, 228, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 138, 137, 137, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 163, 162, + 34, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 253, 252, 252, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 246, 245, 245, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 143, + 143, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 209, 208, 208, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 139, 138, 10, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 188, 187, + 187, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 254, 253, 253, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 183, 182, 54, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 160, + 32, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 187, 186, 58, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 172, 171, 171, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 143, + 143, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 157, 156, 156, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 230, 229, 229, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 220, 219, + 219, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 194, 193, 193, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 161, 160, 32, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 207, 206, + 78, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 240, 239, 239, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 157, 156, 156, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 130, 129, + 129, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 154, 153, 153, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 185, 184, 56, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 216, 215, + 215, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 208, 207, 207, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 181, 180, 180, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 244, 243, + 243, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 232, 231, 231, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 227, 226, 98, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 235, 234, + 106, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 169, 168, 40, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 243, 242, 114, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 200, 199, + 199, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 171, 170, 42, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 170, 169, 169, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 211, 210, + 82, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 192, 191, 191, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 236, 235, 235, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 223, 222, + 94, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 223, 222, 94, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 237, 236, 236, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 140, 139, + 139, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 153, 152, 24, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 249, 248, 120, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 186, 185, + 185, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 155, 154, 26, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 201, 200, 72, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 210, 209, + 209, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 134, 133, 133, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 213, 212, 212, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 217, 216, + 88, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 208, 207, 207, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 171, 170, 42, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 145, 144, + 144, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 221, 220, 220, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 216, 215, 215, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 180, 179, + 179, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 243, 242, 114, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 175, 174, 46, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 156, 155, + 155, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 190, 189, 189, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 151, 150, 22, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 248, 247, + 247, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 199, 198, 70, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 170, 169, 169, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 252, 251, + 251, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 218, 217, 217, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 135, 135, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 131, 130, + 2, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 244, 243, 243, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 158, 157, 157, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 172, + 172, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 179, 179, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 214, 213, 213, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 241, + 241, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 191, 190, 62, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 239, 238, 110, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 237, + 237, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 150, 149, 149, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 197, 196, 196, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 209, 208, + 208, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 195, 194, 66, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 154, 153, 153, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 145, 144, + 144, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 196, 195, 195, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 254, 126, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 251, 250, + 122, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 254, 253, 253, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 139, 138, 10, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 225, 224, + 96, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 164, 163, 163, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 141, 140, 140, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 202, 201, + 201, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 129, 128, 0, 183, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 165, 164, 164, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 176, 175, + 175, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 230, 229, 229, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 131, 130, 2, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 156, 155, + 155, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 203, 202, 74, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 176, 175, 175, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 140, + 140, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 194, 193, 193, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 137, 136, 8, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 203, 202, + 74, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 172, 171, 171, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 205, 204, 204, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 251, 250, + 122, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 245, 244, 244, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 202, 201, 201, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 135, + 135, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 179, 178, 50, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 220, 219, 219, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 132, 131, + 131, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 221, 220, 220, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 234, 233, 233, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 249, 248, + 120, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 163, 162, 34, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 218, 217, 217, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 219, 218, + 90, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 226, 225, 225, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 142, 141, 141, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 232, 231, + 231, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 207, 206, 78, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 234, 233, 233, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 179, 178, + 50, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 130, 129, 129, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 174, 173, 173, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 185, 184, + 56, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 198, 197, 197, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 173, 172, 172, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 187, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 175, 174, 46, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 212, 211, 211, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 152, 151, + 151, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 237, 236, 236, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 229, 228, 228, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 201, 200, + 72, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 196, 195, 195, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 150, 149, 149, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 177, 176, + 176, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 248, 247, 247, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 184, 183, 183, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 147, 146, + 18, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 241, 240, 240, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 166, 165, 165, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 150, + 22, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 254, 126, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 174, 173, 173, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 233, 232, + 104, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 199, 198, 70, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 178, 177, 177, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 192, 191, + 191, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 227, 226, 98, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 189, 188, 188, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 143, 142, + 14, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 148, 147, 147, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 133, 132, 132, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 147, 146, + 18, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 238, 237, 237, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 226, 225, 225, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 152, 151, + 151, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 195, 194, 66, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 206, 205, 205, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 241, 240, + 240, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 160, 159, 159, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 240, 239, 239, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 193, 192, + 192, 55, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 252, 251, 251, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 228, 227, 227, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 186, + 58, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 204, 203, 203, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 224, 223, 223, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 162, 161, + 161, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 217, 216, 88, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 138, 137, 137, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 191, 190, + 62, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 214, 213, 213, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 165, 164, 164, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 253, 252, + 252, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 236, 235, 235, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 247, 246, 118, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 181, 180, + 180, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 183, 182, 54, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 134, 133, 133, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 205, + 205, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 193, 192, 192, 183, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 168, 167, 167, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 211, 210, + 82, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 235, 234, 106, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 188, 187, 187, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 159, 158, + 30, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 177, 176, 176, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 239, 238, 110, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 59, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 184, 183, 183, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 167, 166, 38, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 198, 197, + 197, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 214, 86, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 164, 163, 163, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 133, 132, + 132, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 200, 199, 199, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 147, 147, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 188, + 188, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 205, 204, 204, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 250, 249, 249, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 182, 181, + 181, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 146, 145, 145, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 212, 211, 211, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 231, 230, + 102, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 153, 152, 24, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 142, 141, 141, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 225, 224, + 96, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 149, 148, 148, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 222, 221, 221, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 166, 165, + 165, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 135, 134, 6, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 169, 168, 40, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 246, 245, + 245, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 219, 218, 90, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 167, 166, 38, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 129, 128, + 0, 55, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 250, 249, 249, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 233, 232, 104, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 197, 196, + 196, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 228, 227, 227, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 213, 212, 212, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 162, 161, + 161, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 224, 223, 223, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 247, 246, 118, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 215, 214, + 86, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 242, 241, 241, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 245, 244, 244, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 89, 0, + 0, 7, 70, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 88, 24, 0, 7, + 70, 126, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, + 100, 32, 0, 4, 50, 16, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 6, 0, 0, 0, + 27, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 70, 128, + 48, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 4, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 5, 50, 0, 16, 0, + 2, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 4, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 5, 0, 0, 0, 230, 10, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 52, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 52, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 52, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 0, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 51, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 32, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 57, 70, + 188, 31, 56, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 1, 64, 0, 0, 0, 0, + 128, 63, 30, 0, 0, 8, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 159, 241, 126, 50, 0, + 0, 10, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 56, 32, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 75, 0, 0, 5, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 140, 0, + 0, 11, 34, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 11, 18, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 8, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 6, 144, + 144, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 52, 0, 0, 0, 6, 0, + 0, 0, 0, 1, 0, 0, + 2, 0, 0, 0, 28, 0, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h new file mode 100644 index 000000000..5cb5f7499 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h @@ -0,0 +1,491 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeCasSharpenConstants +// { +// +// int2 xe_cas_output_offset; // Offset: 0 Size: 8 +// float xe_cas_sharpness_post_setup; // Offset: 8 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeCasSharpenConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 5 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +iadd r1.xyzw, r0.xyxy, l(-1, 0, 0, -1) +mov r2.xy, r1.zwzz +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r3.xyz, r0.xyzw, T0[0].xyzw +iadd r0.xyzw, r0.xyxy, l(0, 1, 1, 0) +mov r4.xy, r0.zwzz +mov r4.zw, l(0,0,0,0) +ld r4.xyz, r4.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mul r2.xyz, r2.xyzx, r2.xyzx +mul r1.xyz, r1.xyzx, r1.xyzx +mul r0.w, r3.y, r3.y +mul r4.xyz, r4.xyzx, r4.xyzx +mul r0.xyz, r0.xyzx, r0.xyzx +min r1.w, r0.w, r4.y +min r1.w, r1.w, r1.y +min r2.w, r0.y, r2.y +min r1.w, r1.w, r2.w +max r0.w, r0.w, r4.y +max r0.w, r0.w, r1.y +max r2.w, r0.y, r2.y +max r0.w, r0.w, r2.w +iadd r2.w, -r0.w, l(0x7ef07ebb) +add r0.w, -r0.w, l(1.000000) +min r0.w, r0.w, r1.w +mul_sat r0.w, r2.w, r0.w +ushr r0.w, r0.w, l(1) +iadd r0.w, r0.w, l(0x1fbc4639) +mul r0.w, r0.w, CB0[0][0].z +mad r1.w, r0.w, l(4.000000), l(1.000000) +iadd r2.w, -r1.w, l(0x7ef19fff) +mad r1.w, -r2.w, r1.w, l(2.000000) +mul r1.w, r1.w, r2.w +mul r1.xyz, r0.wwww, r1.xyzx +mad r1.xyz, r2.xyzx, r0.wwww, r1.xyzx +mad r1.xyz, r4.xyzx, r0.wwww, r1.xyzx +mad r0.xyz, r0.xyzx, r0.wwww, r1.xyzx +mad r0.xyz, r3.xyzx, r3.xyzx, r0.xyzx +mul_sat r0.xyz, r1.wwww, r0.xyzx +sqrt o0.xyz, r0.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 49 instruction slots used +#endif + +const BYTE guest_output_ffx_cas_sharpen_ps[] = +{ + 68, 88, 66, 67, 2, 226, + 230, 16, 201, 205, 207, 54, + 189, 193, 184, 163, 140, 156, + 247, 96, 1, 0, 0, 0, + 40, 9, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 4, 2, 0, 0, 56, 2, + 0, 0, 108, 2, 0, 0, + 140, 8, 0, 0, 82, 68, + 69, 70, 200, 1, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 160, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 67, 97, 115, + 83, 104, 97, 114, 112, 101, + 110, 67, 111, 110, 115, 116, + 97, 110, 116, 115, 0, 171, + 171, 171, 151, 0, 0, 0, + 2, 0, 0, 0, 200, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 24, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 52, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 88, 1, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 124, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 120, 101, + 95, 99, 97, 115, 95, 111, + 117, 116, 112, 117, 116, 95, + 111, 102, 102, 115, 101, 116, + 0, 105, 110, 116, 50, 0, + 171, 171, 1, 0, 2, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 1, + 0, 0, 120, 101, 95, 99, + 97, 115, 95, 115, 104, 97, + 114, 112, 110, 101, 115, 115, + 95, 112, 111, 115, 116, 95, + 115, 101, 116, 117, 112, 0, + 102, 108, 111, 97, 116, 0, + 171, 171, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 116, 1, + 0, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 49, 0, + 73, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171, 83, 72, 69, 88, + 24, 6, 0, 0, 81, 0, + 0, 0, 134, 1, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 7, 70, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 88, 24, 0, 7, + 70, 126, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, + 100, 32, 0, 4, 50, 16, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 5, 0, 0, 0, + 27, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 70, 128, + 48, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 4, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 5, 50, 0, 16, 0, + 2, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 4, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 4, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 0, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 51, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 32, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 57, 70, + 188, 31, 56, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 1, 64, 0, 0, 0, 0, + 128, 63, 30, 0, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 159, 241, 126, 50, 0, + 0, 10, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 56, 32, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 75, 0, 0, 5, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 49, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 27, 0, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h new file mode 100644 index 000000000..3c9a5a926 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h @@ -0,0 +1,2098 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeFsrEasuConstants +// { +// +// float2 xe_fsr_easu_input_output_size_ratio;// Offset: 0 Size: 8 +// float2 xe_fsr_easu_input_size_inv; // Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_sampler_linear_clamp sampler NA NA S0 s0 1 +// xe_texture texture float3 2d T0 t0 1 +// XeFsrEasuConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_sampler S0[0:0], mode_default, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 22 +mul r0.w, CB0[0][0].w, l(4.000000) +mad r0.xy, CB0[0][0].xyxx, l(0.500000, 0.500000, 0.000000, 0.000000), l(-0.500000, -0.500000, 0.000000, 0.000000) +mul r1.xyz, CB0[0][0].zwwz, l(1.000000, 1.000000, -1.000000, 0.000000) +ftou r2.xy, v0.xyxx +utof r2.xy, r2.xyxx +mad r0.xy, r2.xyxx, CB0[0][0].xyxx, r0.xyxx +round_ni r2.xy, r0.xyxx +add r0.xy, r0.xyxx, -r2.xyxx +mad r1.xy, r2.xyxx, r1.xyxx, r1.xzxx +mad r2.xyzw, CB0[0][0].zwzw, l(-1.000000, 2.000000, 1.000000, 2.000000), r1.xyxy +mov r0.z, l(0) +add r0.zw, r0.zzzw, r1.xxxy +gather4 r1.zw, r1.xyxx, T0[0].zwxy, S0[0].x +gather4 r3.xy, r1.xyxx, T0[0].xyzw, S0[0].y +gather4 r4.xz, r1.xyxx, T0[0].xzyw, S0[0].z +gather4 r5.xyzw, r2.xyxx, T0[0].xyzw, S0[0].x +gather4 r6.xyzw, r2.xyxx, T0[0].xyzw, S0[0].y +gather4 r7.xyzw, r2.xyxx, T0[0].yzxw, S0[0].z +gather4 r8.xyzw, r2.zwzz, T0[0].xyzw, S0[0].x +gather4 r9.xyzw, r2.zwzz, T0[0].xyzw, S0[0].y +gather4 r2.xyzw, r2.zwzz, T0[0].xyzw, S0[0].z +gather4 r1.xy, r0.zwzz, T0[0].zwxy, S0[0].x +gather4 r3.zw, r0.zwzz, T0[0].xyzw, S0[0].y +gather4 r10.zw, r0.zwzz, T0[0].xyzw, S0[0].z +mad r0.zw, r1.zzzw, l(0.000000, 0.000000, 0.500000, 0.500000), r3.xxxy +mad r0.zw, r4.xxxz, l(0.000000, 0.000000, 0.500000, 0.500000), r0.zzzw +mad r11.xyzw, r5.zwyx, l(0.500000, 0.500000, 0.500000, 0.500000), r6.zwyx +mad r11.xyzw, r7.ywxz, l(0.500000, 0.500000, 0.500000, 0.500000), r11.xyzw +mad r12.xyzw, r8.xyzw, l(0.500000, 0.500000, 0.500000, 0.500000), r9.xyzw +mad r12.xyzw, r2.xyzw, l(0.500000, 0.500000, 0.500000, 0.500000), r12.xyzw +mad r13.xy, r1.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000), r3.zwzz +mad r13.xy, r10.zwzz, l(0.500000, 0.500000, 0.000000, 0.000000), r13.xyxx +add r14.xyzw, -r0.xyxy, l(1.000000, 1.000000, 0.000000, -1.000000) +mul r4.w, r14.y, r14.x +add r15.xyzw, -r11.xyxz, r12.wwzx +add r16.xyz, -r11.yxwy, r11.xzzx +max r13.zw, |r15.xxxw|, |r16.xxxz| +iadd r13.zw, -r13.zzzw, l(0, 0, 0x7ef07ebb, 0x7ef07ebb) +mul_sat r11.y, r13.z, |r15.y| +mul r11.y, r11.y, r11.y +add r16.xz, -r0.zzzz, r11.xxzx +max r0.z, |r16.x|, |r16.y| +iadd r0.z, -r0.z, l(0x7ef07ebb) +mul_sat r0.z, r0.z, |r16.z| +mul r0.z, r0.z, r0.z +mul r0.z, r4.w, r0.z +mad r0.z, r11.y, r4.w, r0.z +mul r14.xy, r0.xyxx, r14.yxyy +add r17.xyz, -r12.wwxw, r12.zxyz +max r15.xw, |r15.xxxw|, |r17.xxxz| +iadd r15.xw, -r15.xxxw, l(0x7ef07ebb, 0, 0, 0x7ef07ebb) +mul r11.y, r14.x, r15.z +mad r11.y, r15.y, r4.w, r11.y +mul_sat r12.z, r15.x, |r15.z| +mul r12.z, r12.z, r12.z +mad r0.z, r12.z, r14.x, r0.z +add r15.xy, -r0.wwww, r12.wxww +max r0.w, |r15.x|, |r17.y| +iadd r0.w, -r0.w, l(0x7ef07ebb) +mul r12.z, r14.x, r15.y +mad r4.w, r16.z, r4.w, r12.z +mul_sat r0.w, r0.w, |r15.y| +mul r0.w, r0.w, r0.w +mad r0.z, r0.w, r14.x, r0.z +add r12.yz, -r11.wwzw, r12.xxyx +mad r0.w, r12.y, r14.y, r11.y +mul_sat r11.y, r13.w, |r12.y| +mul r11.y, r11.y, r11.y +mad r0.z, r11.y, r14.y, r0.z +add r11.xy, -r11.zxzz, r13.yyyy +max r11.x, |r16.y|, |r11.x| +iadd r11.x, -r11.x, l(0x7ef07ebb) +mad r4.w, r11.y, r14.y, r4.w +mul_sat r11.x, r11.x, |r11.y| +mul r11.x, r11.x, r11.x +mad r0.z, r11.x, r14.y, r0.z +mul r11.x, r0.y, r0.x +mad r15.y, r12.z, r11.x, r0.w +mul_sat r0.w, r15.w, |r12.z| +mul r0.w, r0.w, r0.w +mad r0.z, r0.w, r11.x, r0.z +add r11.yz, -r12.xxwx, r13.xxxx +max r0.w, |r17.y|, |r11.y| +iadd r0.w, -r0.w, l(0x7ef07ebb) +mad r15.z, r11.z, r11.x, r4.w +mul_sat r0.w, r0.w, |r11.z| +mul r0.w, r0.w, r0.w +mad r0.z, r0.w, r11.x, r0.z +mul r11.xy, r15.yzyy, r15.yzyy +add r0.w, r11.y, r11.x +lt r4.w, r0.w, l(0.000031) +ushr r0.w, r0.w, l(1) +iadd r0.w, -r0.w, l(0x5f347d74) +movc r0.w, r4.w, l(1.000000), r0.w +movc r15.x, r4.w, l(1.000000), r15.y +mul r11.xy, r0.wwww, r15.xzxx +mul r0.z, r0.z, l(0.500000) +mul r0.z, r0.z, r0.z +dp2 r0.w, r11.xyxx, r11.xyxx +max r4.w, |r11.y|, |r11.x| +iadd r4.w, -r4.w, l(0x7ef07ebb) +mad r0.w, r0.w, r4.w, l(-1.000000) +mad r12.x, r0.w, r0.z, l(1.000000) +mad r12.yz, r0.zzzz, l(0.000000, -0.500000, -0.290000, 0.000000), l(0.000000, 1.000000, 0.500000, 0.000000) +iadd r0.z, -r12.z, l(0x7ef07ebb) +mov r13.x, r8.w +mov r13.y, r9.w +mov r13.z, r2.w +mov r15.x, r5.y +mov r15.y, r6.y +mov r15.z, r7.x +min r16.xyz, r13.xyzx, r15.xyzx +mov r17.x, r5.z +mov r17.y, r6.z +mov r17.z, r7.y +min r16.xyz, r16.xyzx, r17.xyzx +mov r18.x, r8.x +mov r18.y, r9.x +mov r18.z, r2.x +min r16.xyz, r16.xyzx, r18.xyzx +max r19.xyz, r13.xyzx, r15.xyzx +max r19.xyz, r17.xyzx, r19.xyzx +max r19.xyz, r18.xyzx, r19.xyzx +dp2 r14.x, r14.zwzz, r11.xyxx +mul r0.w, r11.x, r14.w +mad r14.y, r14.z, -r11.y, r0.w +mul r5.yz, r12.xxyx, r14.xxyx +dp2 r0.w, r5.yzyy, r5.yzyy +min r0.w, r0.z, r0.w +mad r2.w, r0.w, l(0.400000), l(-1.000000) +mad r0.w, r12.z, r0.w, l(-1.000000) +mul r2.w, r2.w, r2.w +mul r0.w, r0.w, r0.w +mad r2.w, r2.w, l(1.562500), l(-0.562500) +mul r4.w, r0.w, r2.w +mov r14.x, r1.z +mov r14.y, r3.x +mov r14.z, r4.x +add r20.xyzw, -r0.xyxy, l(1.000000, -1.000000, -1.000000, 1.000000) +dp2 r21.y, r20.xyxx, r11.xyxx +mul r5.yz, r11.xxxx, r20.yywy +mad r21.zw, r20.xxxz, -r11.yyyy, r5.yyyz +mul r5.yz, r12.xxyx, r21.yyzy +dp2 r1.z, r5.yzyy, r5.yzyy +min r1.z, r0.z, r1.z +mad r3.x, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r3.x, r3.x, r3.x +mul r1.z, r1.z, r1.z +mad r3.x, r3.x, l(1.562500), l(-0.562500) +mul r1.z, r1.z, r3.x +mov r4.x, r1.w +mov r4.y, r3.y +mul r4.xyz, r1.zzzz, r4.xyzx +mad r4.xyz, r14.xyzx, r4.wwww, r4.xyzx +mad r0.w, r2.w, r0.w, r1.z +dp2 r21.x, r20.zwzz, r11.xyxx +mul r1.zw, r12.xxxy, r21.xxxw +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mov r7.x, r5.x +mov r7.y, r6.x +mad r4.xyz, r7.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +add r14.xyzw, -r0.xyxy, l(0.000000, 1.000000, -1.000000, 0.000000) +dp2 r20.y, r14.xyxx, r11.xyxx +mul r1.zw, r11.xxxx, r14.yyyw +mad r20.zw, r14.xxxz, -r11.yyyy, r1.zzzw +mul r1.zw, r12.xxxy, r20.yyyz +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mad r4.xyz, r15.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +dp2 r3.x, -r0.xyxx, r11.xyxx +mul r1.z, -r0.y, r11.x +mad r3.y, r0.x, r11.y, r1.z +mul r1.zw, r12.xxxy, r3.xxxy +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mad r4.xyz, r17.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +dp2 r20.x, r14.zwzz, r11.xyxx +mul r1.zw, r12.xxxy, r20.xxxw +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mov r7.z, r5.w +mov r7.x, r6.w +mad r4.xyz, r7.zxwz, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +add r5.xyzw, -r0.xyxy, l(1.000000, 1.000000, 2.000000, 1.000000) +dp2 r6.y, r5.xyxx, r11.xyxx +mul r1.zw, r11.xxxx, r5.yyyw +mad r6.zw, r5.xxxz, -r11.yyyy, r1.zzzw +mul r1.zw, r12.xxxy, r6.yyyz +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mad r4.xyz, r18.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +dp2 r6.x, r5.zwzz, r11.xyxx +mul r1.zw, r12.xxxy, r6.xxxw +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mov r5.x, r8.y +mov r5.y, r9.y +mov r5.z, r2.y +mad r4.xyz, r5.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +add r5.xyzw, -r0.xyxy, l(2.000000, 0.000000, 1.000000, 0.000000) +dp2 r6.y, r5.xyxx, r11.xyxx +mul r1.zw, r11.xxxx, r5.yyyw +mad r6.zw, r5.xxxz, -r11.yyyy, r1.zzzw +mul r1.zw, r12.xxxy, r6.yyyz +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mov r2.x, r8.z +mov r2.y, r9.z +mad r2.xyz, r2.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +dp2 r6.x, r5.zwzz, r11.xyxx +mul r1.zw, r12.xxxy, r6.xxxw +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mad r2.xyz, r13.xyzx, r2.wwww, r2.xyzx +mad r0.w, r1.w, r1.z, r0.w +add r4.xyzw, -r0.xyxy, l(1.000000, 2.000000, 0.000000, 2.000000) +dp2 r5.y, r4.xyxx, r11.xyxx +mul r0.xy, r11.xxxx, r4.ywyy +mad r5.zw, r4.xxxz, -r11.yyyy, r0.xxxy +mul r0.xy, r12.xyxx, r5.yzyy +dp2 r0.x, r0.xyxx, r0.xyxx +min r0.x, r0.z, r0.x +mad r0.y, r0.x, l(0.400000), l(-1.000000) +mad r0.x, r12.z, r0.x, l(-1.000000) +mul r0.xy, r0.xyxx, r0.xyxx +mad r0.y, r0.y, l(1.562500), l(-0.562500) +mul r1.z, r0.x, r0.y +mov r10.x, r1.x +mov r10.y, r3.z +mad r1.xzw, r10.xxyz, r1.zzzz, r2.xxyz +mad r0.x, r0.y, r0.x, r0.w +dp2 r5.x, r4.zwzz, r11.xyxx +mul r0.yw, r12.xxxy, r5.xxxw +dp2 r0.y, r0.ywyy, r0.ywyy +min r0.y, r0.z, r0.y +mad r0.z, r0.y, l(0.400000), l(-1.000000) +mad r0.y, r12.z, r0.y, l(-1.000000) +mul r0.yz, r0.yyzy, r0.yyzy +mad r0.z, r0.z, l(1.562500), l(-0.562500) +mul r0.w, r0.y, r0.z +mov r10.x, r1.y +mov r10.y, r3.w +mad r1.xyz, r10.xywx, r0.wwww, r1.xzwx +mad r0.x, r0.z, r0.y, r0.x +rcp r0.x, r0.x +mul r0.xyz, r0.xxxx, r1.xyzx +max r0.xyz, r0.xyzx, r16.xyzx +min o0.xyz, r0.xyzx, r19.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 299 instruction slots used +#endif + +const BYTE guest_output_ffx_fsr_easu_ps[] = +{ + 68, 88, 66, 67, 240, 45, + 22, 153, 167, 152, 10, 67, + 48, 29, 75, 57, 104, 138, + 197, 43, 1, 0, 0, 0, + 236, 40, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 36, 2, 0, 0, 88, 2, + 0, 0, 140, 2, 0, 0, + 80, 40, 0, 0, 82, 68, + 69, 70, 232, 1, 0, 0, + 1, 0, 0, 0, 236, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 191, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 180, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 120, 101, 95, 115, 97, 109, + 112, 108, 101, 114, 95, 108, + 105, 110, 101, 97, 114, 95, + 99, 108, 97, 109, 112, 0, + 120, 101, 95, 116, 101, 120, + 116, 117, 114, 101, 0, 88, + 101, 70, 115, 114, 69, 97, + 115, 117, 67, 111, 110, 115, + 116, 97, 110, 116, 115, 0, + 171, 171, 215, 0, 0, 0, + 2, 0, 0, 0, 4, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 84, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 128, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 164, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 128, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 120, 101, + 95, 102, 115, 114, 95, 101, + 97, 115, 117, 95, 105, 110, + 112, 117, 116, 95, 111, 117, + 116, 112, 117, 116, 95, 115, + 105, 122, 101, 95, 114, 97, + 116, 105, 111, 0, 102, 108, + 111, 97, 116, 50, 0, 171, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 1, 0, 0, + 120, 101, 95, 102, 115, 114, + 95, 101, 97, 115, 117, 95, + 105, 110, 112, 117, 116, 95, + 115, 105, 122, 101, 95, 105, + 110, 118, 0, 77, 105, 99, + 114, 111, 115, 111, 102, 116, + 32, 40, 82, 41, 32, 72, + 76, 83, 76, 32, 83, 104, + 97, 100, 101, 114, 32, 67, + 111, 109, 112, 105, 108, 101, + 114, 32, 49, 48, 46, 49, + 0, 171, 73, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 3, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 188, 37, 0, 0, + 81, 0, 0, 0, 111, 9, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 90, 0, + 0, 6, 70, 110, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 100, 32, 0, 4, + 50, 16, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 22, 0, + 0, 0, 56, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 50, 0, 0, 17, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 191, 0, 0, + 0, 191, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 12, 114, 0, 16, 0, + 1, 0, 0, 0, 230, 139, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 191, + 0, 0, 0, 0, 28, 0, + 0, 5, 50, 0, 16, 0, + 2, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 86, 0, 0, 5, 50, 0, + 16, 0, 2, 0, 0, 0, + 70, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 11, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 2, 0, 0, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 65, 0, + 0, 5, 50, 0, 16, 0, + 2, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 50, 0, 16, 0, 1, 0, + 0, 0, 70, 0, 16, 0, + 2, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 134, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 14, + 242, 0, 16, 0, 2, 0, + 0, 0, 230, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 191, 0, 0, 0, 64, + 0, 0, 128, 63, 0, 0, + 0, 64, 70, 4, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 194, 0, + 16, 0, 0, 0, 0, 0, + 166, 14, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 1, 0, 0, 0, 109, 0, + 0, 11, 194, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 230, 116, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 11, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 11, + 82, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 1, 0, 0, 0, 134, 125, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 0, + 16, 0, 2, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 11, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 0, 16, 0, 2, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 11, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 0, 16, 0, + 2, 0, 0, 0, 150, 124, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 242, 0, 16, 0, + 8, 0, 0, 0, 230, 10, + 16, 0, 2, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 11, 242, 0, + 16, 0, 9, 0, 0, 0, + 230, 10, 16, 0, 2, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 11, + 242, 0, 16, 0, 2, 0, + 0, 0, 230, 10, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 50, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 230, 116, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 11, 194, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 11, + 194, 0, 16, 0, 10, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 6, 4, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 12, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 8, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 166, 14, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 11, 0, 0, 0, 230, 1, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 63, 230, 1, 16, 0, + 6, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 11, 0, 0, 0, 214, 8, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 63, 70, 14, 16, 0, + 11, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 63, 70, 14, 16, 0, + 9, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 63, 70, 14, 16, 0, + 12, 0, 0, 0, 50, 0, + 0, 12, 50, 0, 16, 0, + 13, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 230, 10, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 12, 50, 0, 16, 0, + 13, 0, 0, 0, 230, 10, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 13, 0, 0, 0, 0, 0, + 0, 11, 242, 0, 16, 0, + 14, 0, 0, 0, 70, 4, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 14, 0, + 0, 0, 10, 0, 16, 0, + 14, 0, 0, 0, 0, 0, + 0, 8, 242, 0, 16, 0, + 15, 0, 0, 0, 70, 8, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 246, 2, + 16, 0, 12, 0, 0, 0, + 0, 0, 0, 8, 114, 0, + 16, 0, 16, 0, 0, 0, + 22, 7, 16, 128, 65, 0, + 0, 0, 11, 0, 0, 0, + 134, 2, 16, 0, 11, 0, + 0, 0, 52, 0, 0, 9, + 194, 0, 16, 0, 13, 0, + 0, 0, 6, 12, 16, 128, + 129, 0, 0, 0, 15, 0, + 0, 0, 6, 8, 16, 128, + 129, 0, 0, 0, 16, 0, + 0, 0, 30, 0, 0, 11, + 194, 0, 16, 0, 13, 0, + 0, 0, 166, 14, 16, 128, + 65, 0, 0, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 187, 126, 240, 126, + 187, 126, 240, 126, 56, 32, + 0, 8, 34, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 13, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 15, 0, 0, 0, + 56, 0, 0, 7, 34, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 0, 0, + 0, 8, 82, 0, 16, 0, + 16, 0, 0, 0, 166, 10, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 6, 2, + 16, 0, 11, 0, 0, 0, + 52, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 128, 129, 0, + 0, 0, 16, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 16, 0, 0, 0, + 30, 0, 0, 8, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 32, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 16, 0, 0, 0, 56, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 50, 0, + 16, 0, 14, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 22, 5, 16, 0, + 14, 0, 0, 0, 0, 0, + 0, 8, 114, 0, 16, 0, + 17, 0, 0, 0, 246, 12, + 16, 128, 65, 0, 0, 0, + 12, 0, 0, 0, 38, 9, + 16, 0, 12, 0, 0, 0, + 52, 0, 0, 9, 146, 0, + 16, 0, 15, 0, 0, 0, + 6, 12, 16, 128, 129, 0, + 0, 0, 15, 0, 0, 0, + 6, 8, 16, 128, 129, 0, + 0, 0, 17, 0, 0, 0, + 30, 0, 0, 11, 146, 0, + 16, 0, 15, 0, 0, 0, + 6, 12, 16, 128, 65, 0, + 0, 0, 15, 0, 0, 0, + 2, 64, 0, 0, 187, 126, + 240, 126, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 34, 0, 16, 0, 11, 0, + 0, 0, 10, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 15, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 56, 32, 0, 8, 66, 0, + 16, 0, 12, 0, 0, 0, + 10, 0, 16, 0, 15, 0, + 0, 0, 42, 0, 16, 128, + 129, 0, 0, 0, 15, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 50, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 10, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 50, 0, + 16, 0, 15, 0, 0, 0, + 246, 15, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 54, 15, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 128, + 129, 0, 0, 0, 15, 0, + 0, 0, 26, 0, 16, 128, + 129, 0, 0, 0, 17, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 56, 0, + 0, 7, 66, 0, 16, 0, + 12, 0, 0, 0, 10, 0, + 16, 0, 14, 0, 0, 0, + 26, 0, 16, 0, 15, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 16, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 56, 32, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 15, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 8, + 98, 0, 16, 0, 12, 0, + 0, 0, 246, 14, 16, 128, + 65, 0, 0, 0, 11, 0, + 0, 0, 6, 1, 16, 0, + 12, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 14, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 56, 32, + 0, 8, 34, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 12, 0, 0, 0, + 56, 0, 0, 7, 34, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 14, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 50, 0, 16, 0, + 11, 0, 0, 0, 38, 10, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 86, 5, + 16, 0, 13, 0, 0, 0, + 52, 0, 0, 9, 18, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 16, 0, 0, 0, + 10, 0, 16, 128, 129, 0, + 0, 0, 11, 0, 0, 0, + 30, 0, 0, 8, 18, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 50, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 14, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 56, 32, 0, 8, + 18, 0, 16, 0, 11, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 11, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 15, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 32, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 15, 0, + 0, 0, 42, 0, 16, 128, + 129, 0, 0, 0, 12, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 98, 0, + 16, 0, 11, 0, 0, 0, + 6, 3, 16, 128, 65, 0, + 0, 0, 12, 0, 0, 0, + 6, 0, 16, 0, 13, 0, + 0, 0, 52, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 129, 0, 0, 0, 17, 0, + 0, 0, 26, 0, 16, 128, + 129, 0, 0, 0, 11, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 50, 0, + 0, 9, 66, 0, 16, 0, + 15, 0, 0, 0, 42, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 56, 32, + 0, 8, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 128, 129, 0, + 0, 0, 11, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 11, 0, 0, 0, 150, 5, + 16, 0, 15, 0, 0, 0, + 150, 5, 16, 0, 15, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 49, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 56, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 116, 125, 52, 95, 55, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 58, 0, 16, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 18, 0, 16, 0, + 15, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 26, 0, 16, 0, + 15, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 11, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 134, 0, 16, 0, 15, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 56, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 15, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 11, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 52, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 128, + 129, 0, 0, 0, 11, 0, + 0, 0, 10, 0, 16, 128, + 129, 0, 0, 0, 11, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 18, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 50, 0, + 0, 15, 98, 0, 16, 0, + 12, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 191, + 225, 122, 148, 190, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 30, 0, + 0, 8, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 128, 65, 0, 0, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 187, 126, 240, 126, + 54, 0, 0, 5, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 15, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 15, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 15, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 17, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 17, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 17, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 51, 0, + 0, 7, 114, 0, 16, 0, + 16, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 18, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 18, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 18, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 51, 0, 0, 7, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 70, 2, + 16, 0, 18, 0, 0, 0, + 52, 0, 0, 7, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 52, 0, + 0, 7, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 19, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 15, 0, 0, 7, 18, 0, + 16, 0, 14, 0, 0, 0, + 230, 10, 16, 0, 14, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 14, 0, + 0, 0, 42, 0, 16, 0, + 14, 0, 0, 0, 26, 0, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 98, 0, + 16, 0, 5, 0, 0, 0, + 6, 1, 16, 0, 12, 0, + 0, 0, 6, 1, 16, 0, + 14, 0, 0, 0, 15, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 150, 5, + 16, 0, 5, 0, 0, 0, + 150, 5, 16, 0, 5, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 1, 64, + 0, 0, 0, 0, 128, 191, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 14, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 14, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 11, 242, 0, + 16, 0, 20, 0, 0, 0, + 70, 4, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 191, + 0, 0, 128, 191, 0, 0, + 128, 63, 15, 0, 0, 7, + 34, 0, 16, 0, 21, 0, + 0, 0, 70, 0, 16, 0, + 20, 0, 0, 0, 70, 0, + 16, 0, 11, 0, 0, 0, + 56, 0, 0, 7, 98, 0, + 16, 0, 5, 0, 0, 0, + 6, 0, 16, 0, 11, 0, + 0, 0, 86, 7, 16, 0, + 20, 0, 0, 0, 50, 0, + 0, 10, 194, 0, 16, 0, + 21, 0, 0, 0, 6, 8, + 16, 0, 20, 0, 0, 0, + 86, 5, 16, 128, 65, 0, + 0, 0, 11, 0, 0, 0, + 86, 9, 16, 0, 5, 0, + 0, 0, 56, 0, 0, 7, + 98, 0, 16, 0, 5, 0, + 0, 0, 6, 1, 16, 0, + 12, 0, 0, 0, 86, 6, + 16, 0, 21, 0, 0, 0, + 15, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 150, 5, 16, 0, 5, 0, + 0, 0, 150, 5, 16, 0, + 5, 0, 0, 0, 51, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 205, 204, 204, 62, + 1, 64, 0, 0, 0, 0, + 128, 191, 50, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 191, 56, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 200, 63, 1, 64, 0, 0, + 0, 0, 16, 191, 56, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 166, 10, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 246, 15, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 15, 0, + 0, 7, 18, 0, 16, 0, + 21, 0, 0, 0, 230, 10, + 16, 0, 20, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 6, 4, 16, 0, + 12, 0, 0, 0, 6, 12, + 16, 0, 21, 0, 0, 0, + 15, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 51, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 205, 204, 204, 62, + 1, 64, 0, 0, 0, 0, + 128, 191, 50, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 191, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 200, 63, 1, 64, + 0, 0, 0, 0, 16, 191, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 11, + 242, 0, 16, 0, 14, 0, + 0, 0, 70, 4, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 191, + 0, 0, 0, 0, 15, 0, + 0, 7, 34, 0, 16, 0, + 20, 0, 0, 0, 70, 0, + 16, 0, 14, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 11, 0, 0, 0, 86, 13, + 16, 0, 14, 0, 0, 0, + 50, 0, 0, 10, 194, 0, + 16, 0, 20, 0, 0, 0, + 6, 8, 16, 0, 14, 0, + 0, 0, 86, 5, 16, 128, + 65, 0, 0, 0, 11, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 86, 9, 16, 0, 20, 0, + 0, 0, 15, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 15, 0, 0, 8, 18, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 8, + 66, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 6, 4, 16, 0, 3, 0, + 0, 0, 15, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 15, 0, 0, 7, 18, 0, + 16, 0, 20, 0, 0, 0, + 230, 10, 16, 0, 14, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 6, 12, 16, 0, 20, 0, + 0, 0, 15, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 38, 11, + 16, 0, 7, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 11, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 4, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 64, 0, 0, 128, 63, + 15, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 86, 13, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 10, + 194, 0, 16, 0, 6, 0, + 0, 0, 6, 8, 16, 0, + 5, 0, 0, 0, 86, 5, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 194, 0, + 16, 0, 1, 0, 0, 0, + 6, 4, 16, 0, 12, 0, + 0, 0, 86, 9, 16, 0, + 6, 0, 0, 0, 15, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 1, 0, + 0, 0, 51, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 1, 64, + 0, 0, 0, 0, 128, 191, + 50, 0, 0, 9, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 194, 0, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 200, 63, 1, 64, 0, 0, + 0, 0, 16, 191, 56, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 15, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 230, 10, 16, 0, + 5, 0, 0, 0, 70, 0, + 16, 0, 11, 0, 0, 0, + 56, 0, 0, 7, 194, 0, + 16, 0, 1, 0, 0, 0, + 6, 4, 16, 0, 12, 0, + 0, 0, 6, 12, 16, 0, + 6, 0, 0, 0, 15, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 1, 0, + 0, 0, 51, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 1, 64, + 0, 0, 0, 0, 128, 191, + 50, 0, 0, 9, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 194, 0, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 200, 63, 1, 64, 0, 0, + 0, 0, 16, 191, 56, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 11, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 4, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 128, 63, + 0, 0, 0, 0, 15, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 11, 0, 0, 0, 86, 13, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 194, 0, + 16, 0, 6, 0, 0, 0, + 6, 8, 16, 0, 5, 0, + 0, 0, 86, 5, 16, 128, + 65, 0, 0, 0, 11, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 86, 9, 16, 0, 6, 0, + 0, 0, 15, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 15, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 230, 10, + 16, 0, 5, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 6, 4, 16, 0, + 12, 0, 0, 0, 6, 12, + 16, 0, 6, 0, 0, 0, + 15, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 51, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 205, 204, 204, 62, + 1, 64, 0, 0, 0, 0, + 128, 191, 50, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 191, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 200, 63, 1, 64, + 0, 0, 0, 0, 16, 191, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 11, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 4, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 0, 64, + 15, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 194, 0, 16, 0, 5, 0, + 0, 0, 6, 8, 16, 0, + 4, 0, 0, 0, 86, 5, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 6, 4, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 12, 0, + 0, 0, 150, 5, 16, 0, + 5, 0, 0, 0, 15, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 51, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 1, 64, + 0, 0, 0, 0, 128, 191, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 200, 63, 1, 64, 0, 0, + 0, 0, 16, 191, 56, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 50, 0, 0, 9, 210, 0, + 16, 0, 1, 0, 0, 0, + 6, 9, 16, 0, 10, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 6, 9, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 15, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 230, 10, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 162, 0, 16, 0, + 0, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 6, 12, 16, 0, 5, 0, + 0, 0, 15, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 214, 5, 16, 0, + 0, 0, 0, 0, 214, 5, + 16, 0, 0, 0, 0, 0, + 51, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 98, 0, 16, 0, + 0, 0, 0, 0, 86, 6, + 16, 0, 0, 0, 0, 0, + 86, 6, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 3, + 16, 0, 10, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 134, 3, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 129, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 52, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 51, 0, 0, 7, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 43, 1, 0, 0, + 22, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 239, 0, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h new file mode 100644 index 000000000..71dd6c93b --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h @@ -0,0 +1,1457 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeFsrRcasConstants +// { +// +// int2 xe_fsr_rcas_output_offset; // Offset: 0 Size: 8 +// float xe_fsr_rcas_sharpness_post_setup;// Offset: 8 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeFsrRcasConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.001003, 0, 0, 0}, + { 0.000881, 0, 0, 0}, + { 0.001693, 0, 0, 0}, + { -0.001555, 0, 0, 0}, + { 0.001279, 0, 0, 0}, + { -0.000605, 0, 0, 0}, + { 0.001065, 0, 0, 0}, + { -0.001386, 0, 0, 0}, + { 0.001356, 0, 0, 0}, + { 0.000513, 0, 0, 0}, + { 0.001218, 0, 0, 0}, + { -0.001601, 0, 0, 0}, + { 0.000590, 0, 0, 0}, + { -0.000283, 0, 0, 0}, + { 0.001111, 0, 0, 0}, + { -0.001417, 0, 0, 0}, + { 0.001448, 0, 0, 0}, + { -0.000544, 0, 0, 0}, + { 0.000130, 0, 0, 0}, + { -0.001203, 0, 0, 0}, + { 0.000437, 0, 0, 0}, + { -0.001049, 0, 0, 0}, + { 0.000620, 0, 0, 0}, + { -0.000483, 0, 0, 0}, + { 0.001877, 0, 0, 0}, + { -0.001095, 0, 0, 0}, + { -0.000100, 0, 0, 0}, + { -0.000528, 0, 0, 0}, + { 0.001432, 0, 0, 0}, + { -0.001938, 0, 0, 0}, + { -0.000697, 0, 0, 0}, + { 0.000038, 0, 0, 0}, + { 0.000712, 0, 0, 0}, + { -0.001310, 0, 0, 0}, + { 0.001095, 0, 0, 0}, + { -0.000299, 0, 0, 0}, + { 0.001754, 0, 0, 0}, + { -0.001677, 0, 0, 0}, + { 0.001478, 0, 0, 0}, + { -0.000038, 0, 0, 0}, + { 0.000789, 0, 0, 0}, + { -0.001831, 0, 0, 0}, + { 0.000299, 0, 0, 0}, + { 0.000988, 0, 0, 0}, + { -0.001172, 0, 0, 0}, + { 0.000176, 0, 0, 0}, + { 0.001647, 0, 0, 0}, + { -0.001585, 0, 0, 0}, + { 0.000345, 0, 0, 0}, + { 0.001861, 0, 0, 0}, + { -0.001769, 0, 0, 0}, + { -0.000866, 0, 0, 0}, + { 0.000896, 0, 0, 0}, + { 0.000161, 0, 0, 0}, + { -0.000927, 0, 0, 0}, + { -0.001524, 0, 0, 0}, + { -0.000651, 0, 0, 0}, + { 0.001294, 0, 0, 0}, + { -0.000804, 0, 0, 0}, + { -0.001463, 0, 0, 0}, + { 0.001800, 0, 0, 0}, + { -0.000850, 0, 0, 0}, + { 0.000850, 0, 0, 0}, + { -0.000452, 0, 0, 0}, + { -0.001065, 0, 0, 0}, + { -0.000146, 0, 0, 0}, + { 0.000237, 0, 0, 0}, + { 0.001417, 0, 0, 0}, + { -0.000590, 0, 0, 0}, + { -0.000191, 0, 0, 0}, + { 0.001601, 0, 0, 0}, + { 0.001019, 0, 0, 0}, + { 0.000406, 0, 0, 0}, + { -0.000207, 0, 0, 0}, + { 0.001585, 0, 0, 0}, + { 0.000651, 0, 0, 0}, + { -0.000069, 0, 0, 0}, + { 0.000421, 0, 0, 0}, + { -0.001647, 0, 0, 0}, + { 0.001371, 0, 0, 0}, + { 0.000927, 0, 0, 0}, + { -0.000666, 0, 0, 0}, + { 0.001187, 0, 0, 0}, + { -0.001448, 0, 0, 0}, + { 0.000574, 0, 0, 0}, + { -0.001892, 0, 0, 0}, + { 0.000758, 0, 0, 0}, + { -0.001294, 0, 0, 0}, + { 0.001922, 0, 0, 0}, + { -0.001662, 0, 0, 0}, + { -0.001034, 0, 0, 0}, + { -0.000498, 0, 0, 0}, + { -0.001861, 0, 0, 0}, + { 0.001203, 0, 0, 0}, + { -0.000329, 0, 0, 0}, + { -0.001371, 0, 0, 0}, + { 0.001631, 0, 0, 0}, + { -0.001846, 0, 0, 0}, + { 0.000728, 0, 0, 0}, + { -0.000911, 0, 0, 0}, + { 0.001815, 0, 0, 0}, + { -0.001141, 0, 0, 0}, + { -0.000375, 0, 0, 0}, + { 0.000100, 0, 0, 0}, + { -0.000743, 0, 0, 0}, + { 0.001172, 0, 0, 0}, + { 0.000069, 0, 0, 0}, + { 0.001494, 0, 0, 0}, + { 0.000973, 0, 0, 0}, + { -0.000957, 0, 0, 0}, + { 0.001938, 0, 0, 0}, + { 0.000528, 0, 0, 0}, + { 0.000054, 0, 0, 0}, + { -0.001248, 0, 0, 0}, + { -0.000268, 0, 0, 0}, + { 0.001540, 0, 0, 0}, + { -0.000008, 0, 0, 0}, + { 0.000314, 0, 0, 0}, + { 0.001340, 0, 0, 0}, + { -0.001754, 0, 0, 0}, + { 0.000498, 0, 0, 0}, + { -0.001187, 0, 0, 0}, + { 0.000774, 0, 0, 0}, + { -0.001340, 0, 0, 0}, + { 0.000268, 0, 0, 0}, + { -0.001478, 0, 0, 0}, + { -0.000130, 0, 0, 0}, + { -0.000774, 0, 0, 0}, + { 0.001310, 0, 0, 0}, + { 0.000391, 0, 0, 0}, + { 0.000957, 0, 0, 0}, + { -0.000467, 0, 0, 0}, + { -0.001540, 0, 0, 0}, + { 0.001034, 0, 0, 0}, + { -0.000682, 0, 0, 0}, + { 0.001677, 0, 0, 0}, + { 0.001003, 0, 0, 0}, + { -0.000421, 0, 0, 0}, + { 0.001785, 0, 0, 0}, + { -0.000237, 0, 0, 0}, + { -0.000620, 0, 0, 0}, + { 0.001662, 0, 0, 0}, + { 0.000835, 0, 0, 0}, + { -0.001723, 0, 0, 0}, + { -0.001080, 0, 0, 0}, + { 0.001769, 0, 0, 0}, + { -0.000789, 0, 0, 0}, + { -0.001785, 0, 0, 0}, + { 0.000682, 0, 0, 0}, + { -0.000988, 0, 0, 0}, + { -0.001325, 0, 0, 0}, + { -0.000176, 0, 0, 0}, + { -0.001509, 0, 0, 0}, + { 0.000329, 0, 0, 0}, + { -0.001953, 0, 0, 0}, + { 0.000666, 0, 0, 0}, + { -0.001616, 0, 0, 0}, + { 0.001157, 0, 0, 0}, + { 0.000452, 0, 0, 0}, + { -0.000437, 0, 0, 0}, + { 0.000191, 0, 0, 0}, + { -0.001494, 0, 0, 0}, + { 0.001141, 0, 0, 0}, + { 0.000084, 0, 0, 0}, + { 0.001892, 0, 0, 0}, + { 0.001402, 0, 0, 0}, + { 0.000559, 0, 0, 0}, + { 0.000115, 0, 0, 0}, + { 0.001264, 0, 0, 0}, + { -0.000574, 0, 0, 0}, + { -0.000973, 0, 0, 0}, + { 0.001325, 0, 0, 0}, + { 0.000222, 0, 0, 0}, + { -0.000758, 0, 0, 0}, + { -0.001356, 0, 0, 0}, + { 0.001463, 0, 0, 0}, + { 0.000866, 0, 0, 0}, + { -0.000360, 0, 0, 0}, + { 0.000544, 0, 0, 0}, + { -0.001126, 0, 0, 0}, + { -0.000253, 0, 0, 0}, + { -0.000559, 0, 0, 0}, + { -0.001815, 0, 0, 0}, + { 0.001723, 0, 0, 0}, + { -0.001157, 0, 0, 0}, + { 0.000743, 0, 0, 0}, + { 0.001570, 0, 0, 0}, + { -0.000115, 0, 0, 0}, + { -0.001218, 0, 0, 0}, + { 0.001831, 0, 0, 0}, + { 0.000023, 0, 0, 0}, + { -0.001922, 0, 0, 0}, + { 0.001739, 0, 0, 0}, + { -0.000712, 0, 0, 0}, + { 0.001555, 0, 0, 0}, + { -0.001708, 0, 0, 0}, + { 0.001233, 0, 0, 0}, + { 0.000207, 0, 0, 0}, + { 0.001049, 0, 0, 0}, + { -0.000728, 0, 0, 0}, + { -0.001631, 0, 0, 0}, + { -0.000314, 0, 0, 0}, + { 0.000483, 0, 0, 0}, + { -0.001800, 0, 0, 0}, + { 0.000942, 0, 0, 0}, + { -0.000345, 0, 0, 0}, + { 0.000697, 0, 0, 0}, + { -0.001019, 0, 0, 0}, + { -0.001570, 0, 0, 0}, + { -0.000023, 0, 0, 0}, + { -0.001279, 0, 0, 0}, + { 0.000804, 0, 0, 0}, + { -0.000896, 0, 0, 0}, + { -0.001432, 0, 0, 0}, + { 0.000605, 0, 0, 0}, + { -0.000084, 0, 0, 0}, + { 0.000911, 0, 0, 0}, + { 0.001953, 0, 0, 0}, + { -0.001402, 0, 0, 0}, + { -0.000636, 0, 0, 0}, + { 0.001509, 0, 0, 0}, + { -0.000820, 0, 0, 0}, + { 0.001248, 0, 0, 0}, + { 0.000253, 0, 0, 0}, + { 0.001524, 0, 0, 0}, + { 0.001126, 0, 0, 0}, + { 0.000360, 0, 0, 0}, + { -0.000391, 0, 0, 0}, + { 0.001907, 0, 0, 0}, + { 0.001386, 0, 0, 0}, + { -0.001111, 0, 0, 0}, + { 0.001616, 0, 0, 0}, + { -0.000881, 0, 0, 0}, + { 0.000146, 0, 0, 0}, + { 0.001080, 0, 0, 0}, + { -0.000054, 0, 0, 0}, + { 0.000283, 0, 0, 0}, + { -0.001693, 0, 0, 0}, + { -0.001264, 0, 0, 0}, + { -0.000513, 0, 0, 0}, + { -0.000161, 0, 0, 0}, + { -0.001877, 0, 0, 0}, + { -0.000835, 0, 0, 0}, + { 0.000636, 0, 0, 0}, + { 0.000008, 0, 0, 0}, + { -0.001907, 0, 0, 0}, + { -0.000222, 0, 0, 0}, + { 0.000375, 0, 0, 0}, + { -0.001739, 0, 0, 0}, + { -0.000406, 0, 0, 0}, + { -0.001233, 0, 0, 0}, + { 0.001708, 0, 0, 0}, + { -0.000942, 0, 0, 0}, + { 0.000820, 0, 0, 0}, + { 0.001846, 0, 0, 0}, + { 0.000467, 0, 0, 0} } +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 10 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +iadd r1.xyzw, r0.xyxy, l(-1, 0, 0, -1) +mov r2.xy, r1.zwzz +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r3.xyz, r0.xyzw, T0[0].xyzw +iadd r4.xyzw, r0.xyxy, l(0, 1, 1, 0) +mov r5.xy, r4.zwzz +mov r5.zw, l(0,0,0,0) +ld r5.xyz, r5.xyzw, T0[0].xyzw +mov r4.zw, l(0,0,0,0) +ld r4.xyz, r4.xyzw, T0[0].xyzw +min r6.xyz, r1.xyzx, r5.xyzx +min r6.xyz, r2.xyzx, r6.xyzx +min r6.xyz, r4.xyzx, r6.xyzx +max r7.xyz, r1.xyzx, r5.xyzx +max r7.xyz, r2.xyzx, r7.xyzx +max r7.xyz, r4.xyzx, r7.xyzx +min r8.xyz, r3.xyzx, r6.xyzx +mul r9.xyz, r7.xyzx, l(4.000000, 4.000000, 4.000000, 0.000000) +rcp r9.xyz, r9.xyzx +mul r8.xyz, r8.xyzx, r9.xyzx +max r7.xyz, r3.xyzx, r7.xyzx +add r7.xyz, -r7.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000) +mad r6.xyz, r6.xyzx, l(4.000000, 4.000000, 4.000000, 0.000000), l(-4.000000, -4.000000, -4.000000, 0.000000) +rcp r6.xyz, r6.xyzx +mul r6.xyz, r6.xyzx, r7.xyzx +max r6.xyz, r6.xyzx, -r8.xyzx +max r0.z, r6.z, r6.y +max r0.z, r0.z, r6.x +min r0.z, r0.z, l(0.000000) +max r0.z, r0.z, l(-0.187500) +mul r0.z, r0.z, CB0[0][0].z +mad r0.w, r0.z, l(4.000000), l(1.000000) +iadd r1.w, -r0.w, l(0x7ef19fff) +mad r0.w, -r1.w, r0.w, l(2.000000) +mul r0.w, r0.w, r1.w +mul r1.xyz, r1.xyzx, r0.zzzz +mad r1.xyz, r0.zzzz, r2.xyzx, r1.xyzx +mad r1.xyz, r0.zzzz, r4.xyzx, r1.xyzx +mad r1.xyz, r0.zzzz, r5.xyzx, r1.xyzx +add r1.xyz, r3.xyzx, r1.xyzx +bfi r0.y, l(4), l(4), r0.y, l(0) +bfi r0.x, l(4), l(0), r0.x, r0.y +mad o0.xyz, r1.xyzx, r0.wwww, icb[r0.x + 0].xxxx +mov o0.w, l(1.000000) +ret +// Approximately 51 instruction slots used +#endif + +const BYTE guest_output_ffx_fsr_rcas_dither_ps[] = +{ + 68, 88, 66, 67, 171, 87, + 217, 222, 87, 57, 211, 199, + 141, 108, 123, 139, 108, 18, + 226, 124, 1, 0, 0, 0, + 192, 25, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 8, 2, 0, 0, 60, 2, + 0, 0, 112, 2, 0, 0, + 36, 25, 0, 0, 82, 68, + 69, 70, 204, 1, 0, 0, + 1, 0, 0, 0, 172, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 164, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 70, 115, 114, + 82, 99, 97, 115, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 171, 171, 151, 0, + 0, 0, 2, 0, 0, 0, + 196, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 20, 1, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 52, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 88, 1, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 128, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 102, 115, 114, + 95, 114, 99, 97, 115, 95, + 111, 117, 116, 112, 117, 116, + 95, 111, 102, 102, 115, 101, + 116, 0, 105, 110, 116, 50, + 0, 171, 1, 0, 2, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 1, + 0, 0, 120, 101, 95, 102, + 115, 114, 95, 114, 99, 97, + 115, 95, 115, 104, 97, 114, + 112, 110, 101, 115, 115, 95, + 112, 111, 115, 116, 95, 115, + 101, 116, 117, 112, 0, 102, + 108, 111, 97, 116, 0, 171, + 0, 0, 3, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 121, 1, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 3, + 0, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 172, 22, + 0, 0, 81, 0, 0, 0, + 171, 5, 0, 0, 106, 8, + 0, 1, 53, 24, 0, 0, + 2, 4, 0, 0, 132, 131, + 131, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 231, 230, 102, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 222, 221, 221, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 203, + 203, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 168, 167, 167, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 158, 30, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 140, 139, + 139, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 182, 181, 181, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 178, 177, 177, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 134, + 6, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 160, 159, 159, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 210, 209, 209, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 155, 154, + 26, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 149, 148, 148, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 145, 145, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 186, 185, + 185, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 190, 189, 189, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 143, 142, 14, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, + 8, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 158, 157, 157, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 229, 228, 228, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 137, + 137, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 163, 162, 34, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 253, 252, 252, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 246, 245, + 245, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 144, 143, 143, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 209, 208, 208, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 138, + 10, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 188, 187, 187, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 254, 253, 253, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 183, 182, + 54, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 161, 160, 32, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 187, 186, 58, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 172, 171, + 171, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 144, 143, 143, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 157, 156, 156, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 230, 229, + 229, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 220, 219, 219, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 194, 193, 193, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 160, + 32, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 207, 206, 78, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 240, 239, 239, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 157, 156, + 156, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 130, 129, 129, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 154, 153, 153, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 185, 184, + 56, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 216, 215, 215, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 208, 207, 207, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 181, 180, + 180, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 244, 243, 243, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 231, 231, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 227, 226, + 98, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 235, 234, 106, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 169, 168, 40, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 243, 242, + 114, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 200, 199, 199, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 171, 170, 42, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 169, + 169, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 211, 210, 82, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 192, 191, 191, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 235, + 235, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 223, 222, 94, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 223, 222, 94, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 236, + 236, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 139, 139, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 153, 152, 24, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 249, 248, + 120, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 186, 185, 185, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 155, 154, 26, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 201, 200, + 72, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 210, 209, 209, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 134, 133, 133, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 212, + 212, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 217, 216, 88, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 208, 207, 207, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 171, 170, + 42, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 145, 144, 144, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 220, 220, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 216, 215, + 215, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 179, 179, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 243, 242, 114, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 175, 174, + 46, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 156, 155, 155, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 190, 189, 189, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 150, + 22, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 248, 247, 247, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 199, 198, 70, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 169, + 169, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 252, 251, 251, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 218, 217, 217, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 135, + 135, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 131, 130, 2, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 244, 243, 243, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 158, 157, + 157, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 173, 172, 172, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 180, 179, 179, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 213, + 213, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 242, 241, 241, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 191, 190, 62, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 238, + 110, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 238, 237, 237, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 150, 149, 149, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 197, 196, + 196, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 209, 208, 208, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 194, 66, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 154, 153, + 153, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 145, 144, 144, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 196, 195, 195, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 254, + 126, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 251, 250, 122, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 254, 253, 253, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 138, + 10, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 225, 224, 96, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 164, 163, 163, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 140, + 140, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 202, 201, 201, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 129, 128, 0, 183, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 164, + 164, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 176, 175, 175, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 230, 229, 229, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 131, 130, + 2, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 156, 155, 155, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 203, 202, 74, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 176, 175, + 175, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 141, 140, 140, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 194, 193, 193, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, + 8, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 203, 202, 74, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 172, 171, 171, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 205, 204, + 204, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 251, 250, 122, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 245, 244, 244, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 202, 201, + 201, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 136, 135, 135, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 179, 178, 50, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 220, 219, + 219, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 132, 131, 131, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 220, 220, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 233, + 233, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 249, 248, 120, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 163, 162, 34, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 218, 217, + 217, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 219, 218, 90, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 226, 225, 225, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 141, + 141, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 232, 231, 231, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 207, 206, 78, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 233, + 233, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 179, 178, 50, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 130, 129, 129, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 173, + 173, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 185, 184, 56, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 198, 197, 197, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 172, + 172, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 187, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 175, 174, 46, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 211, + 211, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 152, 151, 151, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 237, 236, 236, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 228, + 228, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 201, 200, 72, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 196, 195, 195, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 149, + 149, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 177, 176, 176, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 248, 247, 247, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 184, 183, + 183, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 147, 146, 18, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 241, 240, 240, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 166, 165, + 165, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 151, 150, 22, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 254, 126, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 173, + 173, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 233, 232, 104, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 199, 198, 70, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 178, 177, + 177, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 192, 191, 191, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 227, 226, 98, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 188, + 188, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 143, 142, 14, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 147, 147, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 133, 132, + 132, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 147, 146, 18, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 238, 237, 237, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 226, 225, + 225, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 152, 151, 151, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 194, 66, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 205, + 205, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 241, 240, 240, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 160, 159, 159, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 240, 239, + 239, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 193, 192, 192, 55, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 252, 251, 251, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 228, 227, + 227, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 187, 186, 58, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 204, 203, 203, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 224, 223, + 223, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 162, 161, 161, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 217, 216, 88, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 137, + 137, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 191, 190, 62, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 214, 213, 213, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 164, + 164, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 253, 252, 252, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 236, 235, 235, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 247, 246, + 118, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 181, 180, 180, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 183, 182, 54, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 134, 133, + 133, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 206, 205, 205, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 193, 192, 192, 183, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 168, 167, + 167, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 211, 210, 82, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 235, 234, 106, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 188, 187, + 187, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 159, 158, 30, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 177, 176, 176, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 238, + 110, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 59, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 184, 183, 183, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 166, + 38, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 198, 197, 197, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 215, 214, 86, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 163, + 163, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 133, 132, 132, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 200, 199, 199, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 148, 147, + 147, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 189, 188, 188, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 205, 204, 204, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 250, 249, + 249, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 182, 181, 181, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 145, 145, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 211, + 211, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 231, 230, 102, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 153, 152, 24, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 141, + 141, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 225, 224, 96, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 149, 148, 148, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 222, 221, + 221, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 166, 165, 165, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 135, 134, 6, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 168, + 40, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 246, 245, 245, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 219, 218, 90, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 166, + 38, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 129, 128, 0, 55, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 250, 249, 249, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 233, 232, + 104, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 197, 196, 196, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 228, 227, 227, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 212, + 212, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 162, 161, 161, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 224, 223, 223, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 247, 246, + 118, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 214, 86, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 242, 241, 241, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 245, 244, + 244, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 89, 0, 0, 7, + 70, 142, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 88, 24, 0, 7, 70, 126, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 0, 0, 0, 0, 100, 32, + 0, 4, 50, 16, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 10, 0, 0, 0, 27, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 4, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 54, 0, 0, 5, + 50, 0, 16, 0, 2, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 4, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 0, 16, 0, 5, 0, + 0, 0, 230, 10, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 51, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 51, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 52, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 52, 0, + 0, 7, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 56, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 64, 0, 0, 128, 64, + 0, 0, 128, 64, 0, 0, + 0, 0, 129, 0, 0, 5, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 0, 0, 0, 11, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 50, 0, 0, 15, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 64, + 0, 0, 128, 64, 0, 0, + 128, 64, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 192, 0, 0, 128, 192, + 0, 0, 128, 192, 0, 0, + 0, 0, 129, 0, 0, 5, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 52, 0, 0, 8, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 8, 0, 0, 0, 52, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 52, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 190, 56, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 1, 64, 0, 0, 0, 0, + 128, 63, 30, 0, 0, 8, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 159, 241, 126, 50, 0, + 0, 10, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 0, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 140, 0, 0, 11, + 34, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 140, 0, + 0, 11, 18, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 10, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 6, 144, + 144, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 51, 0, 0, 0, 10, 0, + 0, 0, 0, 1, 0, 0, + 2, 0, 0, 0, 28, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h new file mode 100644 index 000000000..f1c967f88 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h @@ -0,0 +1,498 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeFsrRcasConstants +// { +// +// int2 xe_fsr_rcas_output_offset; // Offset: 0 Size: 8 +// float xe_fsr_rcas_sharpness_post_setup;// Offset: 8 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeFsrRcasConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 9 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +iadd r1.xyzw, r0.xyxy, l(-1, 0, 0, -1) +mov r2.xy, r1.zwzz +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r3.xyz, r0.xyzw, T0[0].xyzw +iadd r0.xyzw, r0.xyxy, l(0, 1, 1, 0) +mov r4.xy, r0.zwzz +mov r4.zw, l(0,0,0,0) +ld r4.xyz, r4.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +min r5.xyz, r1.xyzx, r4.xyzx +min r5.xyz, r2.xyzx, r5.xyzx +min r5.xyz, r0.xyzx, r5.xyzx +max r6.xyz, r1.xyzx, r4.xyzx +max r6.xyz, r2.xyzx, r6.xyzx +max r6.xyz, r0.xyzx, r6.xyzx +min r7.xyz, r3.xyzx, r5.xyzx +mul r8.xyz, r6.xyzx, l(4.000000, 4.000000, 4.000000, 0.000000) +rcp r8.xyz, r8.xyzx +mul r7.xyz, r7.xyzx, r8.xyzx +max r6.xyz, r3.xyzx, r6.xyzx +add r6.xyz, -r6.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000) +mad r5.xyz, r5.xyzx, l(4.000000, 4.000000, 4.000000, 0.000000), l(-4.000000, -4.000000, -4.000000, 0.000000) +rcp r5.xyz, r5.xyzx +mul r5.xyz, r5.xyzx, r6.xyzx +max r5.xyz, r5.xyzx, -r7.xyzx +max r0.w, r5.z, r5.y +max r0.w, r0.w, r5.x +min r0.w, r0.w, l(0.000000) +max r0.w, r0.w, l(-0.187500) +mul r0.w, r0.w, CB0[0][0].z +mad r1.w, r0.w, l(4.000000), l(1.000000) +iadd r2.w, -r1.w, l(0x7ef19fff) +mad r1.w, -r2.w, r1.w, l(2.000000) +mul r1.w, r1.w, r2.w +mul r1.xyz, r1.xyzx, r0.wwww +mad r1.xyz, r0.wwww, r2.xyzx, r1.xyzx +mad r0.xyz, r0.wwww, r0.xyzx, r1.xyzx +mad r0.xyz, r0.wwww, r4.xyzx, r0.xyzx +add r0.xyz, r3.xyzx, r0.xyzx +mul o0.xyz, r1.wwww, r0.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 49 instruction slots used +#endif + +const BYTE guest_output_ffx_fsr_rcas_ps[] = +{ + 68, 88, 66, 67, 185, 223, + 242, 110, 212, 184, 173, 198, + 168, 143, 147, 205, 178, 152, + 68, 191, 1, 0, 0, 0, + 84, 9, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 8, 2, 0, 0, 60, 2, + 0, 0, 112, 2, 0, 0, + 184, 8, 0, 0, 82, 68, + 69, 70, 204, 1, 0, 0, + 1, 0, 0, 0, 172, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 164, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 70, 115, 114, + 82, 99, 97, 115, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 171, 171, 151, 0, + 0, 0, 2, 0, 0, 0, + 196, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 20, 1, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 52, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 88, 1, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 128, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 102, 115, 114, + 95, 114, 99, 97, 115, 95, + 111, 117, 116, 112, 117, 116, + 95, 111, 102, 102, 115, 101, + 116, 0, 105, 110, 116, 50, + 0, 171, 1, 0, 2, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 1, + 0, 0, 120, 101, 95, 102, + 115, 114, 95, 114, 99, 97, + 115, 95, 115, 104, 97, 114, + 112, 110, 101, 115, 115, 95, + 112, 111, 115, 116, 95, 115, + 101, 116, 117, 112, 0, 102, + 108, 111, 97, 116, 0, 171, + 0, 0, 3, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 121, 1, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 3, + 0, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 64, 6, + 0, 0, 81, 0, 0, 0, + 144, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 7, + 70, 142, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 88, 24, 0, 7, 70, 126, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 0, 0, 0, 0, 100, 32, + 0, 4, 50, 16, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 9, 0, 0, 0, 27, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 4, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 54, 0, 0, 5, + 50, 0, 16, 0, 2, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 4, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 0, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 51, 0, 0, 7, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 52, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 52, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 56, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 64, 0, 0, 128, 64, + 0, 0, 128, 64, 0, 0, + 0, 0, 129, 0, 0, 5, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 0, 0, 0, 11, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 50, 0, 0, 15, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 64, + 0, 0, 128, 64, 0, 0, + 128, 64, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 192, 0, 0, 128, 192, + 0, 0, 128, 192, 0, 0, + 0, 0, 129, 0, 0, 5, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 7, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 190, 56, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 1, 64, 0, 0, 0, 0, + 128, 63, 30, 0, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 159, 241, 126, 50, 0, + 0, 10, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 32, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 49, 0, 0, 0, + 9, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 28, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h new file mode 100644 index 000000000..ccdcc1495 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h @@ -0,0 +1,220 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeTriangleStripRectConstants +// { +// +// float2 xe_triangle_strip_rect_offset;// Offset: 0 Size: 8 +// float2 xe_triangle_strip_rect_size;// Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// XeTriangleStripRectConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_VertexID 0 x 0 VERTID uint x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xyzw +// +vs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_input_sgv v0.x, vertex_id +dcl_output_siv o0.xyzw, position +dcl_temps 1 +ushr r0.y, v0.x, l(1) +mov r0.x, v0.x +and r0.xy, r0.xyxx, l(1, 1, 0, 0) +utof r0.xy, r0.xyxx +mad o0.xy, r0.xyxx, CB0[0][0].zwzz, CB0[0][0].xyxx +mov o0.zw, l(0,0,0,1.000000) +ret +// Approximately 7 instruction slots used +#endif + +const BYTE guest_output_triangle_strip_rect_vs[] = +{ + 68, 88, 66, 67, 67, 209, + 250, 163, 3, 195, 64, 100, + 167, 54, 190, 31, 173, 113, + 120, 163, 1, 0, 0, 0, + 216, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 184, 1, 0, 0, 236, 1, + 0, 0, 32, 2, 0, 0, + 60, 3, 0, 0, 82, 68, + 69, 70, 124, 1, 0, 0, + 1, 0, 0, 0, 132, 0, + 0, 0, 1, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 254, 255, 0, 5, 0, 0, + 84, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 101, + 84, 114, 105, 97, 110, 103, + 108, 101, 83, 116, 114, 105, + 112, 82, 101, 99, 116, 67, + 111, 110, 115, 116, 97, 110, + 116, 115, 0, 171, 171, 171, + 100, 0, 0, 0, 2, 0, + 0, 0, 156, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 236, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 20, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 56, 1, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 20, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 116, + 114, 105, 97, 110, 103, 108, + 101, 95, 115, 116, 114, 105, + 112, 95, 114, 101, 99, 116, + 95, 111, 102, 102, 115, 101, + 116, 0, 102, 108, 111, 97, + 116, 50, 0, 171, 171, 171, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 1, 0, 0, + 120, 101, 95, 116, 114, 105, + 97, 110, 103, 108, 101, 95, + 115, 116, 114, 105, 112, 95, + 114, 101, 99, 116, 95, 115, + 105, 122, 101, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 83, 86, 95, 86, 101, 114, + 116, 101, 120, 73, 68, 0, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 83, 72, + 69, 88, 20, 1, 0, 0, + 81, 0, 1, 0, 69, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 96, 0, + 0, 4, 18, 16, 16, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 16, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 16, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 86, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 13, + 50, 32, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 230, 138, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 32, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 63, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 7, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h index 6a0bd31ac..09255e348 100644 --- a/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h @@ -42,10 +42,10 @@ ret const BYTE immediate_ps[] = { - 68, 88, 66, 67, 204, 46, - 131, 39, 62, 129, 239, 95, - 188, 170, 211, 224, 226, 155, - 212, 68, 1, 0, 0, 0, + 68, 88, 66, 67, 218, 200, + 108, 196, 58, 28, 70, 226, + 98, 137, 89, 199, 218, 58, + 155, 172, 1, 0, 0, 0, 0, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 1, 0, 0, 104, 1, @@ -55,7 +55,7 @@ const BYTE immediate_ps[] = 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, + 255, 255, 0, 5, 0, 0, 182, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h index 03385fb28..dc36315ba 100644 --- a/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h @@ -8,7 +8,7 @@ // cbuffer XeImmediateVertexConstants // { // -// float2 xe_viewport_size_inv; // Offset: 0 Size: 8 +// float2 xe_coordinate_space_size_inv;// Offset: 0 Size: 8 // // } // @@ -59,21 +59,21 @@ ret const BYTE immediate_vs[] = { - 68, 88, 66, 67, 88, 56, - 35, 17, 155, 211, 230, 48, - 9, 16, 27, 220, 163, 42, - 194, 218, 1, 0, 0, 0, - 16, 4, 0, 0, 5, 0, + 68, 88, 66, 67, 141, 232, + 76, 204, 152, 38, 127, 131, + 125, 87, 10, 113, 217, 159, + 27, 143, 1, 0, 0, 0, + 24, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, - 100, 1, 0, 0, 212, 1, - 0, 0, 68, 2, 0, 0, - 116, 3, 0, 0, 82, 68, - 69, 70, 40, 1, 0, 0, + 108, 1, 0, 0, 220, 1, + 0, 0, 76, 2, 0, 0, + 124, 3, 0, 0, 82, 68, + 69, 70, 48, 1, 0, 0, 1, 0, 0, 0, 128, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, - 0, 1, 0, 0, 19, 19, + 254, 255, 0, 5, 0, 0, + 8, 1, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, @@ -97,122 +97,123 @@ const BYTE immediate_vs[] = 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, - 220, 0, 0, 0, 0, 0, + 228, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, - 120, 101, 95, 118, 105, 101, - 119, 112, 111, 114, 116, 95, - 115, 105, 122, 101, 95, 105, - 110, 118, 0, 102, 108, 111, - 97, 116, 50, 0, 1, 0, - 3, 0, 1, 0, 2, 0, + 120, 101, 95, 99, 111, 111, + 114, 100, 105, 110, 97, 116, + 101, 95, 115, 112, 97, 99, + 101, 95, 115, 105, 122, 101, + 95, 105, 110, 118, 0, 102, + 108, 111, 97, 116, 50, 0, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 221, 0, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 104, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 213, 0, 0, 0, 77, 105, - 99, 114, 111, 115, 111, 102, - 116, 32, 40, 82, 41, 32, - 72, 76, 83, 76, 32, 83, - 104, 97, 100, 101, 114, 32, - 67, 111, 109, 112, 105, 108, - 101, 114, 32, 49, 48, 46, - 49, 0, 73, 83, 71, 78, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 3, + 0, 0, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 15, + 0, 0, 80, 79, 83, 73, + 84, 73, 79, 78, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 67, 79, 76, 79, + 82, 0, 79, 83, 71, 78, 104, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 3, 3, 0, 0, - 89, 0, 0, 0, 0, 0, + 0, 0, 3, 12, 0, 0, + 80, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, - 0, 0, 3, 3, 0, 0, - 98, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 89, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, - 0, 0, 15, 15, 0, 0, - 80, 79, 83, 73, 84, 73, - 79, 78, 0, 84, 69, 88, - 67, 79, 79, 82, 68, 0, - 67, 79, 76, 79, 82, 0, - 79, 83, 71, 78, 104, 0, - 0, 0, 3, 0, 0, 0, - 8, 0, 0, 0, 80, 0, + 0, 0, 15, 0, 0, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 171, 171, + 83, 72, 69, 88, 40, 1, + 0, 0, 81, 0, 1, 0, + 74, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 7, + 70, 142, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 3, 12, 0, 0, 80, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 15, 0, 0, 0, 89, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 3, 0, - 0, 0, 2, 0, 0, 0, - 15, 0, 0, 0, 84, 69, - 88, 67, 79, 79, 82, 68, - 0, 83, 86, 95, 80, 111, - 115, 105, 116, 105, 111, 110, - 0, 171, 171, 171, 83, 72, - 69, 88, 40, 1, 0, 0, - 81, 0, 1, 0, 74, 0, - 0, 0, 106, 8, 0, 1, - 89, 0, 0, 7, 70, 142, - 48, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 95, 0, - 0, 3, 50, 16, 16, 0, - 0, 0, 0, 0, 95, 0, - 0, 3, 50, 16, 16, 0, - 1, 0, 0, 0, 95, 0, - 0, 3, 242, 16, 16, 0, - 2, 0, 0, 0, 101, 0, - 0, 3, 50, 32, 16, 0, - 0, 0, 0, 0, 101, 0, - 0, 3, 242, 32, 16, 0, - 1, 0, 0, 0, 103, 0, - 0, 4, 242, 32, 16, 0, - 2, 0, 0, 0, 1, 0, - 0, 0, 104, 0, 0, 2, - 1, 0, 0, 0, 56, 0, - 0, 9, 50, 0, 16, 0, - 0, 0, 0, 0, 70, 16, + 95, 0, 0, 3, 50, 16, 16, 0, 0, 0, 0, 0, - 70, 128, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 0, - 0, 15, 50, 32, 16, 0, - 2, 0, 0, 0, 70, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 50, 32, 16, 0, 0, 0, 0, 0, - 2, 64, 0, 0, 0, 0, - 0, 64, 0, 0, 0, 192, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 56, 0, 0, 9, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 15, 50, 32, + 16, 0, 2, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 64, 0, 0, + 0, 192, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 191, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 242, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 8, + 194, 32, 16, 0, 2, 0, 0, 0, 2, 64, 0, 0, - 0, 0, 128, 191, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 54, 0, - 0, 5, 242, 32, 16, 0, - 1, 0, 0, 0, 70, 30, - 16, 0, 2, 0, 0, 0, - 54, 0, 0, 8, 194, 32, - 16, 0, 2, 0, 0, 0, - 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 128, 63, 54, 0, 0, 5, - 50, 32, 16, 0, 0, 0, - 0, 0, 70, 16, 16, 0, - 1, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 148, 0, 0, 0, 6, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 6, 0, - 0, 0, 2, 0, 0, 0, + 0, 0, 128, 63, 54, 0, + 0, 5, 50, 32, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, + 6, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -220,7 +221,7 @@ const BYTE immediate_vs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -232,5 +233,5 @@ const BYTE immediate_vs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 + 0, 0, 0, 0 }; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h new file mode 100644 index 000000000..baf34ac23 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h @@ -0,0 +1,607 @@ +// generated from `xb genspirv` +// source: guest_output_bilinear_dither.frag +const uint8_t guest_output_bilinear_dither_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x7B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x29, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x29, 0x01, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, + 0x72, 0x61, 0x67, 0x43, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x07, 0x00, 0x30, 0x01, 0x00, 0x00, 0x58, 0x65, 0x42, 0x69, + 0x6C, 0x69, 0x6E, 0x65, 0x61, 0x72, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, + 0x6E, 0x74, 0x73, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x62, 0x69, 0x6C, 0x69, 0x6E, + 0x65, 0x61, 0x72, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x62, + 0x69, 0x6C, 0x69, 0x6E, 0x65, 0x61, 0x72, 0x5F, 0x6F, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, 0x6E, 0x76, 0x00, + 0x05, 0x00, 0x03, 0x00, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, + 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x3E, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x29, 0x01, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x30, 0x01, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x3E, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x3E, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0xE7, 0xE6, 0x66, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0xA8, 0xA7, 0xA7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x9F, 0x9E, 0x1E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xB6, 0xB5, 0xB5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x87, 0x86, 0x06, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0xA0, 0x9F, 0x9F, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0xD2, 0xD1, 0xD1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x95, 0x94, 0x94, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x92, 0x91, 0x91, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0xBE, 0xBD, 0xBD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x8F, 0x8E, 0x0E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x9E, 0x9D, 0x9D, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x8A, 0x89, 0x89, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xA3, 0xA2, 0x22, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFC, 0xFC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x90, 0x8F, 0x8F, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0xD1, 0xD0, 0xD0, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xBC, 0xBB, 0xBB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, 0xFE, 0xFD, 0xFD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xA1, 0xA0, 0x20, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0xBB, 0xBA, 0x3A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x90, 0x8F, 0x8F, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0xDC, 0xDB, 0xDB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0xC2, 0xC1, 0xC1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0xCF, 0xCE, 0x4E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x82, 0x81, 0x81, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, + 0xD8, 0xD7, 0xD7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x43, 0x00, 0x00, 0x00, 0xD0, 0xCF, 0xCF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, + 0xF4, 0xF3, 0xF3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x46, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xE7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0xEB, 0xEA, 0x6A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x49, 0x00, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, + 0xC8, 0xC7, 0xC7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4C, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0xD3, 0xD2, 0x52, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0xC0, 0xBF, 0xBF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, + 0xDF, 0xDE, 0x5E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0xDF, 0xDE, 0x5E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x8C, 0x8B, 0x8B, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, + 0xBA, 0xB9, 0xB9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0xD2, 0xD1, 0xD1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5B, 0x00, 0x00, 0x00, 0x86, 0x85, 0x85, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, + 0xD9, 0xD8, 0x58, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5E, 0x00, 0x00, 0x00, 0xD0, 0xCF, 0xCF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x91, 0x90, 0x90, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0xDD, 0xDC, 0xDC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, + 0xB4, 0xB3, 0xB3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, + 0x9C, 0x9B, 0x9B, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0xBE, 0xBD, 0xBD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0xF8, 0xF7, 0xF7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6A, 0x00, 0x00, 0x00, 0xC7, 0xC6, 0x46, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0xFC, 0xFB, 0xFB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6D, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0x83, 0x82, 0x02, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0xF4, 0xF3, 0xF3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xAD, 0xAC, 0xAC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x00, 0x00, 0xB4, 0xB3, 0xB3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, + 0xF2, 0xF1, 0xF1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0xBF, 0xBE, 0x3E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0xEE, 0xED, 0xED, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0xD1, 0xD0, 0xD0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0xC3, 0xC2, 0x42, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x91, 0x90, 0x90, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0xC4, 0xC3, 0xC3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, + 0xFB, 0xFA, 0x7A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x00, 0x00, 0xFE, 0xFD, 0xFD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0xE1, 0xE0, 0x60, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, + 0xCA, 0xC9, 0xC9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0xB7, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, + 0xB0, 0xAF, 0xAF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8B, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, + 0x9C, 0x9B, 0x9B, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x00, 0x00, 0xCB, 0xCA, 0x4A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x8D, 0x8C, 0x8C, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x91, 0x00, 0x00, 0x00, 0xC2, 0xC1, 0xC1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0xCB, 0xCA, 0x4A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0xFB, 0xFA, 0x7A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, + 0x88, 0x87, 0x87, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x32, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, + 0x84, 0x83, 0x83, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9D, 0x00, 0x00, 0x00, 0xDD, 0xDC, 0xDC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, + 0xF9, 0xF8, 0x78, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA0, 0x00, 0x00, 0x00, 0xA3, 0xA2, 0x22, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, + 0xDB, 0xDA, 0x5A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, + 0xE8, 0xE7, 0xE7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA6, 0x00, 0x00, 0x00, 0xCF, 0xCE, 0x4E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, + 0xB3, 0xB2, 0x32, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA9, 0x00, 0x00, 0x00, 0x82, 0x81, 0x81, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, + 0xB9, 0xB8, 0x38, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0xC6, 0xC5, 0xC5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xBB, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAF, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0x98, 0x97, 0x97, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, + 0xC9, 0xC8, 0x48, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0xC4, 0xC3, 0xC3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, + 0xB1, 0xB0, 0xB0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0xF8, 0xF7, 0xF7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, + 0x93, 0x92, 0x12, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xF1, 0xF0, 0xF0, 0x38, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, + 0x97, 0x96, 0x16, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xE9, 0xE8, 0x68, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0xC7, 0xC6, 0x46, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0xC0, 0xBF, 0xBF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC4, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x8F, 0x8E, 0x0E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x00, 0x00, 0x94, 0x93, 0x93, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x85, 0x84, 0x84, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, + 0x93, 0x92, 0x12, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCA, 0x00, 0x00, 0x00, 0xEE, 0xED, 0xED, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0x98, 0x97, 0x97, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCD, 0x00, 0x00, 0x00, 0xC3, 0xC2, 0x42, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, + 0xF1, 0xF0, 0xF0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD0, 0x00, 0x00, 0x00, 0xA0, 0x9F, 0x9F, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xC1, 0xC0, 0xC0, 0x37, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD3, 0x00, 0x00, 0x00, 0xFC, 0xFB, 0xFB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, + 0xBB, 0xBA, 0x3A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD6, 0x00, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, + 0xA2, 0xA1, 0xA1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD9, 0x00, 0x00, 0x00, 0xD9, 0xD8, 0x58, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0x8A, 0x89, 0x89, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, + 0xBF, 0xBE, 0x3E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDC, 0x00, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, + 0xFD, 0xFC, 0xFC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDF, 0x00, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, + 0xB5, 0xB4, 0xB4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE2, 0x00, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x86, 0x85, 0x85, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, + 0xCE, 0xCD, 0xCD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE5, 0x00, 0x00, 0x00, 0xC1, 0xC0, 0xC0, 0xB7, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0xD3, 0xD2, 0x52, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE8, 0x00, 0x00, 0x00, 0xEB, 0xEA, 0x6A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, + 0x9F, 0x9E, 0x1E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEB, 0x00, 0x00, 0x00, 0xB1, 0xB0, 0xB0, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3B, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0xC6, 0xC5, 0xC5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF1, 0x00, 0x00, 0x00, 0xD7, 0xD6, 0x56, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, + 0x85, 0x84, 0x84, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF4, 0x00, 0x00, 0x00, 0xC8, 0xC7, 0xC7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0x94, 0x93, 0x93, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, + 0xBD, 0xBC, 0xBC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF7, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, + 0xB6, 0xB5, 0xB5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0x92, 0x91, 0x91, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xE7, 0xE6, 0x66, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xE1, 0xE0, 0x60, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x95, 0x94, 0x94, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0xA6, 0xA5, 0xA5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x87, 0x86, 0x06, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, + 0xF6, 0xF5, 0xF5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x01, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x81, 0x80, 0x00, 0x37, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x01, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, + 0xC5, 0xC4, 0xC4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0C, 0x01, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, + 0xA2, 0xA1, 0xA1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, + 0xD7, 0xD6, 0x56, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x12, 0x01, 0x00, 0x00, 0xF2, 0xF1, 0xF1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0x39, + 0x2C, 0x00, 0x03, 0x01, 0x13, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, + 0x4A, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x4D, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x59, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, + 0x6B, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, + 0x6E, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, + 0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, + 0x7A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x7D, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, + 0x86, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, + 0x8C, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00, + 0x9E, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, + 0xA1, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xA4, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, + 0xA7, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, + 0xAA, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, + 0xAD, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, + 0xB0, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, + 0xB3, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, + 0xB6, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, + 0xB9, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, + 0xC5, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, + 0xCB, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, + 0xCE, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, + 0xD1, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, + 0xD4, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, + 0xD7, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, + 0xDA, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, + 0xDD, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, + 0xE3, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, + 0xE6, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, + 0xE9, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, + 0xEC, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, + 0xF2, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, + 0xF5, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, + 0xFB, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, + 0x07, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, + 0x0A, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, + 0x0D, 0x01, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, + 0x13, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x15, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1F, 0x01, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x21, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x27, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x28, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x28, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x2D, 0x01, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x2E, 0x01, 0x00, 0x00, 0x2D, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x04, 0x00, 0x30, 0x01, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x31, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x31, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x2D, 0x01, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x34, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x39, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x39, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x3B, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x3C, 0x01, 0x00, 0x00, + 0x3B, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x3D, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x3D, 0x01, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x2B, 0x00, 0x04, 0x00, 0x2D, 0x01, 0x00, 0x00, + 0x45, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x46, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x4C, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x4E, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x01, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00, 0x4C, 0x01, 0x00, 0x00, + 0x5D, 0x01, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2C, 0x00, 0x06, 0x00, + 0x4C, 0x01, 0x00, 0x00, 0x5F, 0x01, 0x00, 0x00, 0x5E, 0x01, 0x00, 0x00, + 0x5E, 0x01, 0x00, 0x00, 0x5E, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x42, 0x01, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x7A, 0x01, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x1F, 0x01, 0x00, 0x00, 0x69, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x27, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, + 0x29, 0x01, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2E, 0x01, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0x32, 0x01, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x2E, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x2E, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, + 0x2F, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x3C, 0x01, 0x00, 0x00, 0x3F, 0x01, 0x00, 0x00, + 0x3E, 0x01, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x41, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x46, 0x01, 0x00, 0x00, + 0x47, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, + 0x47, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x49, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, + 0x58, 0x00, 0x07, 0x00, 0x27, 0x01, 0x00, 0x00, 0x4B, 0x01, 0x00, 0x00, + 0x3F, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x4E, 0x01, 0x00, 0x00, + 0x4F, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0x4B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x4F, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x4E, 0x01, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x15, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x52, 0x01, 0x00, 0x00, 0x4B, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x51, 0x01, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x4E, 0x01, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, + 0x3A, 0x01, 0x00, 0x00, 0x53, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x4B, 0x01, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x54, 0x01, 0x00, 0x00, + 0x55, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x27, 0x01, 0x00, 0x00, + 0x56, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, + 0x4C, 0x01, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, + 0x56, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x6E, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x7A, 0x01, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, + 0x6E, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x71, 0x01, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x73, 0x01, 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, + 0x71, 0x01, 0x00, 0x00, 0x73, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x69, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x21, 0x01, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00, 0x69, 0x01, 0x00, 0x00, + 0x74, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x4C, 0x01, 0x00, 0x00, 0x5B, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x4C, 0x01, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, + 0x5B, 0x01, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x4C, 0x01, 0x00, 0x00, + 0x60, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x5C, 0x01, 0x00, 0x00, 0x5D, 0x01, 0x00, 0x00, 0x5F, 0x01, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x01, 0x00, 0x00, + 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x4F, 0x01, 0x00, 0x00, 0x62, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x51, 0x01, 0x00, 0x00, + 0x64, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x66, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x54, 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x4E, 0x01, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, + 0x3A, 0x01, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x68, 0x01, 0x00, 0x00, 0x5E, 0x01, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.spv new file mode 100644 index 000000000..9148ff78e Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.txt new file mode 100644 index 000000000..b40cb0bb1 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.txt @@ -0,0 +1,377 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 379 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeBilinearConstants "XeBilinearConstants" + OpMemberName %XeBilinearConstants 0 "xe_bilinear_output_offset" + OpMemberName %XeBilinearConstants 1 "xe_bilinear_output_size_inv" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpName %xe_texture "xe_texture" + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeBilinearConstants 0 Offset 16 + OpMemberDecorate %XeBilinearConstants 1 Offset 24 + OpDecorate %XeBilinearConstants Block + OpDecorate %xe_frag_color Location 0 + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %float = OpTypeFloat 32 + %uint_15 = OpConstant %uint 15 + %uint_256 = OpConstant %uint 256 +%_arr_float_uint_256 = OpTypeArray %float %uint_256 +%float_n0_00100337015 = OpConstant %float -0.00100337015 +%float_0_000880821084 = OpConstant %float 0.000880821084 +%float_0_00169270835 = OpConstant %float 0.00169270835 +%float_n0_00155484071 = OpConstant %float -0.00155484071 +%float_0_00127910543 = OpConstant %float 0.00127910543 +%float_n0_000605085806 = OpConstant %float -0.000605085806 +%float_0_00106464466 = OpConstant %float 0.00106464466 +%float_n0_00138633582 = OpConstant %float -0.00138633582 +%float_0_00135569857 = OpConstant %float 0.00135569857 +%float_0_000513174047 = OpConstant %float 0.000513174047 +%float_0_00121783093 = OpConstant %float 0.00121783093 +%float_n0_00160079659 = OpConstant %float -0.00160079659 +%float_0_00058976718 = OpConstant %float 0.00058976718 +%float_n0_00028339462 = OpConstant %float -0.00028339462 +%float_0_00111060054 = OpConstant %float 0.00111060054 +%float_n0_00141697307 = OpConstant %float -0.00141697307 +%float_0_00144761032 = OpConstant %float 0.00144761032 +%float_n0_0005438113 = OpConstant %float -0.0005438113 +%float_0_00013020834 = OpConstant %float 0.00013020834 +%float_n0_0012025123 = OpConstant %float -0.0012025123 +%float_0_000436580885 = OpConstant %float 0.000436580885 +%float_n0_00104932603 = OpConstant %float -0.00104932603 +%float_0_000620404433 = OpConstant %float 0.000620404433 +%float_n0_000482536765 = OpConstant %float -0.000482536765 +%float_0_00187653187 = OpConstant %float 0.00187653187 +%float_n0_00109528191 = OpConstant %float -0.00109528191 +%float_n9_95710798en05 = OpConstant %float -9.95710798e-05 +%float_n0_000528492674 = OpConstant %float -0.000528492674 +%float_0_0014322917 = OpConstant %float 0.0014322917 +%float_n0_00193780637 = OpConstant %float -0.00193780637 +%float_n0_000696997566 = OpConstant %float -0.000696997566 +%float_3_829657en05 = OpConstant %float 3.829657e-05 +%float_0_000712316192 = OpConstant %float 0.000712316192 +%float_n0_00130974269 = OpConstant %float -0.00130974269 +%float_0_00109528191 = OpConstant %float 0.00109528191 +%float_n0_000298713247 = OpConstant %float -0.000298713247 +%float_0_00175398286 = OpConstant %float 0.00175398286 +%float_n0_00167738972 = OpConstant %float -0.00167738972 +%float_0_00147824758 = OpConstant %float 0.00147824758 +%float_n3_829657en05 = OpConstant %float -3.829657e-05 +%float_0_000788909325 = OpConstant %float 0.000788909325 +%float_n0_00183057599 = OpConstant %float -0.00183057599 +%float_0_000298713247 = OpConstant %float 0.000298713247 +%float_0_000988051528 = OpConstant %float 0.000988051528 +%float_n0_00117187505 = OpConstant %float -0.00117187505 +%float_0_00017616422 = OpConstant %float 0.00017616422 +%float_0_00164675247 = OpConstant %float 0.00164675247 +%float_n0_00158547796 = OpConstant %float -0.00158547796 +%float_0_000344669126 = OpConstant %float 0.000344669126 +%float_0_00186121324 = OpConstant %float 0.00186121324 +%float_n0_00176930148 = OpConstant %float -0.00176930148 +%float_n0_000865502458 = OpConstant %float -0.000865502458 +%float_0_000896139711 = OpConstant %float 0.000896139711 +%float_0_000160845593 = OpConstant %float 0.000160845593 +%float_n0_000926776964 = OpConstant %float -0.000926776964 +%float_n0_00152420346 = OpConstant %float -0.00152420346 +%float_n0_000651041686 = OpConstant %float -0.000651041686 +%float_0_00129442406 = OpConstant %float 0.00129442406 +%float_n0_000804227951 = OpConstant %float -0.000804227951 +%float_n0_00146292895 = OpConstant %float -0.00146292895 +%float_0_00179993873 = OpConstant %float 0.00179993873 +%float_n0_000850183831 = OpConstant %float -0.000850183831 +%float_0_000850183831 = OpConstant %float 0.000850183831 +%float_n0_000451899512 = OpConstant %float -0.000451899512 +%float_n0_00106464466 = OpConstant %float -0.00106464466 +%float_n0_000145526967 = OpConstant %float -0.000145526967 +%float_0_000237438726 = OpConstant %float 0.000237438726 +%float_0_00141697307 = OpConstant %float 0.00141697307 +%float_n0_00058976718 = OpConstant %float -0.00058976718 +%float_n0_000191482846 = OpConstant %float -0.000191482846 +%float_0_00160079659 = OpConstant %float 0.00160079659 +%float_0_00101868878 = OpConstant %float 0.00101868878 +%float_0_000405943632 = OpConstant %float 0.000405943632 +%float_n0_000206801473 = OpConstant %float -0.000206801473 +%float_0_00158547796 = OpConstant %float 0.00158547796 +%float_0_000651041686 = OpConstant %float 0.000651041686 +%float_n6_89338267en05 = OpConstant %float -6.89338267e-05 +%float_0_000421262259 = OpConstant %float 0.000421262259 +%float_n0_00164675247 = OpConstant %float -0.00164675247 +%float_0_00137101719 = OpConstant %float 0.00137101719 +%float_0_000926776964 = OpConstant %float 0.000926776964 +%float_n0_000666360313 = OpConstant %float -0.000666360313 +%float_0_00118719367 = OpConstant %float 0.00118719367 +%float_n0_00144761032 = OpConstant %float -0.00144761032 +%float_0_000574448553 = OpConstant %float 0.000574448553 +%float_n0_00189185049 = OpConstant %float -0.00189185049 +%float_0_000758272072 = OpConstant %float 0.000758272072 +%float_n0_00129442406 = OpConstant %float -0.00129442406 +%float_0_00192248775 = OpConstant %float 0.00192248775 +%float_n0_0016620711 = OpConstant %float -0.0016620711 +%float_n0_00103400741 = OpConstant %float -0.00103400741 +%float_n0_000497855421 = OpConstant %float -0.000497855421 +%float_n0_00186121324 = OpConstant %float -0.00186121324 +%float_0_0012025123 = OpConstant %float 0.0012025123 +%float_n0_0003293505 = OpConstant %float -0.0003293505 +%float_n0_00137101719 = OpConstant %float -0.00137101719 +%float_0_00163143384 = OpConstant %float 0.00163143384 +%float_n0_00184589461 = OpConstant %float -0.00184589461 +%float_0_000727634819 = OpConstant %float 0.000727634819 +%float_n0_000911458337 = OpConstant %float -0.000911458337 +%float_0_00181525736 = OpConstant %float 0.00181525736 +%float_n0_00114123779 = OpConstant %float -0.00114123779 +%float_n0_000375306379 = OpConstant %float -0.000375306379 +%float_9_95710798en05 = OpConstant %float 9.95710798e-05 +%float_n0_000742953445 = OpConstant %float -0.000742953445 +%float_0_00117187505 = OpConstant %float 0.00117187505 +%float_6_89338267en05 = OpConstant %float 6.89338267e-05 +%float_0_0014935662 = OpConstant %float 0.0014935662 +%float_0_000972732843 = OpConstant %float 0.000972732843 +%float_n0_000957414217 = OpConstant %float -0.000957414217 +%float_0_00193780637 = OpConstant %float 0.00193780637 +%float_0_000528492674 = OpConstant %float 0.000528492674 +%float_5_36151965en05 = OpConstant %float 5.36151965e-05 +%float_n0_00124846818 = OpConstant %float -0.00124846818 +%float_n0_000268075994 = OpConstant %float -0.000268075994 +%float_0_00153952208 = OpConstant %float 0.00153952208 +%float_n7_65931418en06 = OpConstant %float -7.65931418e-06 +%float_0_000314031873 = OpConstant %float 0.000314031873 +%float_0_00134037994 = OpConstant %float 0.00134037994 +%float_n0_00175398286 = OpConstant %float -0.00175398286 +%float_0_000497855421 = OpConstant %float 0.000497855421 +%float_n0_00118719367 = OpConstant %float -0.00118719367 +%float_0_000773590698 = OpConstant %float 0.000773590698 +%float_n0_00134037994 = OpConstant %float -0.00134037994 +%float_0_000268075994 = OpConstant %float 0.000268075994 +%float_n0_00147824758 = OpConstant %float -0.00147824758 +%float_n0_00013020834 = OpConstant %float -0.00013020834 +%float_n0_000773590698 = OpConstant %float -0.000773590698 +%float_0_00130974269 = OpConstant %float 0.00130974269 +%float_0_000390625006 = OpConstant %float 0.000390625006 +%float_0_000957414217 = OpConstant %float 0.000957414217 +%float_n0_000467218139 = OpConstant %float -0.000467218139 +%float_n0_00153952208 = OpConstant %float -0.00153952208 +%float_0_00103400741 = OpConstant %float 0.00103400741 +%float_n0_000681678939 = OpConstant %float -0.000681678939 +%float_0_00167738972 = OpConstant %float 0.00167738972 +%float_0_00100337015 = OpConstant %float 0.00100337015 +%float_n0_000421262259 = OpConstant %float -0.000421262259 +%float_0_00178462011 = OpConstant %float 0.00178462011 +%float_n0_000237438726 = OpConstant %float -0.000237438726 +%float_n0_000620404433 = OpConstant %float -0.000620404433 +%float_0_0016620711 = OpConstant %float 0.0016620711 +%float_0_000834865205 = OpConstant %float 0.000834865205 +%float_n0_0017233456 = OpConstant %float -0.0017233456 +%float_n0_00107996329 = OpConstant %float -0.00107996329 +%float_0_00176930148 = OpConstant %float 0.00176930148 +%float_n0_000788909325 = OpConstant %float -0.000788909325 +%float_n0_00178462011 = OpConstant %float -0.00178462011 +%float_0_000681678939 = OpConstant %float 0.000681678939 +%float_n0_000988051528 = OpConstant %float -0.000988051528 +%float_n0_00132506131 = OpConstant %float -0.00132506131 +%float_n0_00017616422 = OpConstant %float -0.00017616422 +%float_n0_00150888483 = OpConstant %float -0.00150888483 +%float_0_0003293505 = OpConstant %float 0.0003293505 +%float_n0_001953125 = OpConstant %float -0.001953125 +%float_0_000666360313 = OpConstant %float 0.000666360313 +%float_n0_00161611522 = OpConstant %float -0.00161611522 +%float_0_00115655642 = OpConstant %float 0.00115655642 +%float_0_000451899512 = OpConstant %float 0.000451899512 +%float_n0_000436580885 = OpConstant %float -0.000436580885 +%float_0_000191482846 = OpConstant %float 0.000191482846 +%float_n0_0014935662 = OpConstant %float -0.0014935662 +%float_0_00114123779 = OpConstant %float 0.00114123779 +%float_8_42524532en05 = OpConstant %float 8.42524532e-05 +%float_0_00189185049 = OpConstant %float 0.00189185049 +%float_0_00140165444 = OpConstant %float 0.00140165444 +%float_0_000559129927 = OpConstant %float 0.000559129927 +%float_0_000114889706 = OpConstant %float 0.000114889706 +%float_0_00126378681 = OpConstant %float 0.00126378681 +%float_n0_000574448553 = OpConstant %float -0.000574448553 +%float_n0_000972732843 = OpConstant %float -0.000972732843 +%float_0_00132506131 = OpConstant %float 0.00132506131 +%float_0_000222120099 = OpConstant %float 0.000222120099 +%float_n0_000758272072 = OpConstant %float -0.000758272072 +%float_n0_00135569857 = OpConstant %float -0.00135569857 +%float_0_00146292895 = OpConstant %float 0.00146292895 +%float_0_000865502458 = OpConstant %float 0.000865502458 +%float_n0_000359987753 = OpConstant %float -0.000359987753 +%float_0_0005438113 = OpConstant %float 0.0005438113 +%float_n0_00112591917 = OpConstant %float -0.00112591917 +%float_n0_000252757367 = OpConstant %float -0.000252757367 +%float_n0_000559129927 = OpConstant %float -0.000559129927 +%float_n0_00181525736 = OpConstant %float -0.00181525736 +%float_0_0017233456 = OpConstant %float 0.0017233456 +%float_n0_00115655642 = OpConstant %float -0.00115655642 +%float_0_000742953445 = OpConstant %float 0.000742953445 +%float_0_00157015934 = OpConstant %float 0.00157015934 +%float_n0_000114889706 = OpConstant %float -0.000114889706 +%float_n0_00121783093 = OpConstant %float -0.00121783093 +%float_0_00183057599 = OpConstant %float 0.00183057599 +%float_2_29779416en05 = OpConstant %float 2.29779416e-05 +%float_n0_00192248775 = OpConstant %float -0.00192248775 +%float_0_00173866423 = OpConstant %float 0.00173866423 +%float_n0_000712316192 = OpConstant %float -0.000712316192 +%float_0_00155484071 = OpConstant %float 0.00155484071 +%float_n0_00170802698 = OpConstant %float -0.00170802698 +%float_0_00123314955 = OpConstant %float 0.00123314955 +%float_0_000206801473 = OpConstant %float 0.000206801473 +%float_0_00104932603 = OpConstant %float 0.00104932603 +%float_n0_000727634819 = OpConstant %float -0.000727634819 +%float_n0_00163143384 = OpConstant %float -0.00163143384 +%float_n0_000314031873 = OpConstant %float -0.000314031873 +%float_0_000482536765 = OpConstant %float 0.000482536765 +%float_n0_00179993873 = OpConstant %float -0.00179993873 +%float_0_00094209559 = OpConstant %float 0.00094209559 +%float_n0_000344669126 = OpConstant %float -0.000344669126 +%float_0_000696997566 = OpConstant %float 0.000696997566 +%float_n0_00101868878 = OpConstant %float -0.00101868878 +%float_n0_00157015934 = OpConstant %float -0.00157015934 +%float_n2_29779416en05 = OpConstant %float -2.29779416e-05 +%float_n0_00127910543 = OpConstant %float -0.00127910543 +%float_0_000804227951 = OpConstant %float 0.000804227951 +%float_n0_000896139711 = OpConstant %float -0.000896139711 +%float_n0_0014322917 = OpConstant %float -0.0014322917 +%float_0_000605085806 = OpConstant %float 0.000605085806 +%float_n8_42524532en05 = OpConstant %float -8.42524532e-05 +%float_0_000911458337 = OpConstant %float 0.000911458337 +%float_0_001953125 = OpConstant %float 0.001953125 +%float_n0_00140165444 = OpConstant %float -0.00140165444 +%float_n0_00063572306 = OpConstant %float -0.00063572306 +%float_0_00150888483 = OpConstant %float 0.00150888483 +%float_n0_000819546578 = OpConstant %float -0.000819546578 +%float_0_00124846818 = OpConstant %float 0.00124846818 +%float_0_000252757367 = OpConstant %float 0.000252757367 +%float_0_00152420346 = OpConstant %float 0.00152420346 +%float_0_00112591917 = OpConstant %float 0.00112591917 +%float_0_000359987753 = OpConstant %float 0.000359987753 +%float_n0_000390625006 = OpConstant %float -0.000390625006 +%float_0_00190716912 = OpConstant %float 0.00190716912 +%float_0_00138633582 = OpConstant %float 0.00138633582 +%float_n0_00111060054 = OpConstant %float -0.00111060054 +%float_0_00161611522 = OpConstant %float 0.00161611522 +%float_n0_000880821084 = OpConstant %float -0.000880821084 +%float_0_000145526967 = OpConstant %float 0.000145526967 +%float_0_00107996329 = OpConstant %float 0.00107996329 +%float_n5_36151965en05 = OpConstant %float -5.36151965e-05 +%float_0_00028339462 = OpConstant %float 0.00028339462 +%float_n0_00169270835 = OpConstant %float -0.00169270835 +%float_n0_00126378681 = OpConstant %float -0.00126378681 +%float_n0_000513174047 = OpConstant %float -0.000513174047 +%float_n0_000160845593 = OpConstant %float -0.000160845593 +%float_n0_00187653187 = OpConstant %float -0.00187653187 +%float_n0_000834865205 = OpConstant %float -0.000834865205 +%float_0_00063572306 = OpConstant %float 0.00063572306 +%float_7_65931418en06 = OpConstant %float 7.65931418e-06 +%float_n0_00190716912 = OpConstant %float -0.00190716912 +%float_n0_000222120099 = OpConstant %float -0.000222120099 +%float_0_000375306379 = OpConstant %float 0.000375306379 +%float_n0_00173866423 = OpConstant %float -0.00173866423 +%float_n0_000405943632 = OpConstant %float -0.000405943632 +%float_n0_00123314955 = OpConstant %float -0.00123314955 +%float_0_00170802698 = OpConstant %float 0.00170802698 +%float_n0_00094209559 = OpConstant %float -0.00094209559 +%float_0_000819546578 = OpConstant %float 0.000819546578 +%float_0_00184589461 = OpConstant %float 0.00184589461 +%float_0_000467218139 = OpConstant %float 0.000467218139 + %276 = OpConstantComposite %_arr_float_uint_256 %float_n0_00100337015 %float_0_000880821084 %float_0_00169270835 %float_n0_00155484071 %float_0_00127910543 %float_n0_000605085806 %float_0_00106464466 %float_n0_00138633582 %float_0_00135569857 %float_0_000513174047 %float_0_00121783093 %float_n0_00160079659 %float_0_00058976718 %float_n0_00028339462 %float_0_00111060054 %float_n0_00141697307 %float_0_00144761032 %float_n0_0005438113 %float_0_00013020834 %float_n0_0012025123 %float_0_000436580885 %float_n0_00104932603 %float_0_000620404433 %float_n0_000482536765 %float_0_00187653187 %float_n0_00109528191 %float_n9_95710798en05 %float_n0_000528492674 %float_0_0014322917 %float_n0_00193780637 %float_n0_000696997566 %float_3_829657en05 %float_0_000712316192 %float_n0_00130974269 %float_0_00109528191 %float_n0_000298713247 %float_0_00175398286 %float_n0_00167738972 %float_0_00147824758 %float_n3_829657en05 %float_0_000788909325 %float_n0_00183057599 %float_0_000298713247 %float_0_000988051528 %float_n0_00117187505 %float_0_00017616422 %float_0_00164675247 %float_n0_00158547796 %float_0_000344669126 %float_0_00186121324 %float_n0_00176930148 %float_n0_000865502458 %float_0_000896139711 %float_0_000160845593 %float_n0_000926776964 %float_n0_00152420346 %float_n0_000651041686 %float_0_00129442406 %float_n0_000804227951 %float_n0_00146292895 %float_0_00179993873 %float_n0_000850183831 %float_0_000850183831 %float_n0_000451899512 %float_n0_00106464466 %float_n0_000145526967 %float_0_000237438726 %float_0_00141697307 %float_n0_00058976718 %float_n0_000191482846 %float_0_00160079659 %float_0_00101868878 %float_0_000405943632 %float_n0_000206801473 %float_0_00158547796 %float_0_000651041686 %float_n6_89338267en05 %float_0_000421262259 %float_n0_00164675247 %float_0_00137101719 %float_0_000926776964 %float_n0_000666360313 %float_0_00118719367 %float_n0_00144761032 %float_0_000574448553 %float_n0_00189185049 %float_0_000758272072 %float_n0_00129442406 %float_0_00192248775 %float_n0_0016620711 %float_n0_00103400741 %float_n0_000497855421 %float_n0_00186121324 %float_0_0012025123 %float_n0_0003293505 %float_n0_00137101719 %float_0_00163143384 %float_n0_00184589461 %float_0_000727634819 %float_n0_000911458337 %float_0_00181525736 %float_n0_00114123779 %float_n0_000375306379 %float_9_95710798en05 %float_n0_000742953445 %float_0_00117187505 %float_6_89338267en05 %float_0_0014935662 %float_0_000972732843 %float_n0_000957414217 %float_0_00193780637 %float_0_000528492674 %float_5_36151965en05 %float_n0_00124846818 %float_n0_000268075994 %float_0_00153952208 %float_n7_65931418en06 %float_0_000314031873 %float_0_00134037994 %float_n0_00175398286 %float_0_000497855421 %float_n0_00118719367 %float_0_000773590698 %float_n0_00134037994 %float_0_000268075994 %float_n0_00147824758 %float_n0_00013020834 %float_n0_000773590698 %float_0_00130974269 %float_0_000390625006 %float_0_000957414217 %float_n0_000467218139 %float_n0_00153952208 %float_0_00103400741 %float_n0_000681678939 %float_0_00167738972 %float_0_00100337015 %float_n0_000421262259 %float_0_00178462011 %float_n0_000237438726 %float_n0_000620404433 %float_0_0016620711 %float_0_000834865205 %float_n0_0017233456 %float_n0_00107996329 %float_0_00176930148 %float_n0_000788909325 %float_n0_00178462011 %float_0_000681678939 %float_n0_000988051528 %float_n0_00132506131 %float_n0_00017616422 %float_n0_00150888483 %float_0_0003293505 %float_n0_001953125 %float_0_000666360313 %float_n0_00161611522 %float_0_00115655642 %float_0_000451899512 %float_n0_000436580885 %float_0_000191482846 %float_n0_0014935662 %float_0_00114123779 %float_8_42524532en05 %float_0_00189185049 %float_0_00140165444 %float_0_000559129927 %float_0_000114889706 %float_0_00126378681 %float_n0_000574448553 %float_n0_000972732843 %float_0_00132506131 %float_0_000222120099 %float_n0_000758272072 %float_n0_00135569857 %float_0_00146292895 %float_0_000865502458 %float_n0_000359987753 %float_0_0005438113 %float_n0_00112591917 %float_n0_000252757367 %float_n0_000559129927 %float_n0_00181525736 %float_0_0017233456 %float_n0_00115655642 %float_0_000742953445 %float_0_00157015934 %float_n0_000114889706 %float_n0_00121783093 %float_0_00183057599 %float_2_29779416en05 %float_n0_00192248775 %float_0_00173866423 %float_n0_000712316192 %float_0_00155484071 %float_n0_00170802698 %float_0_00123314955 %float_0_000206801473 %float_0_00104932603 %float_n0_000727634819 %float_n0_00163143384 %float_n0_000314031873 %float_0_000482536765 %float_n0_00179993873 %float_0_00094209559 %float_n0_000344669126 %float_0_000696997566 %float_n0_00101868878 %float_n0_00157015934 %float_n2_29779416en05 %float_n0_00127910543 %float_0_000804227951 %float_n0_000896139711 %float_n0_0014322917 %float_0_000605085806 %float_n8_42524532en05 %float_0_000911458337 %float_0_001953125 %float_n0_00140165444 %float_n0_00063572306 %float_0_00150888483 %float_n0_000819546578 %float_0_00124846818 %float_0_000252757367 %float_0_00152420346 %float_0_00112591917 %float_0_000359987753 %float_n0_000390625006 %float_0_00190716912 %float_0_00138633582 %float_n0_00111060054 %float_0_00161611522 %float_n0_000880821084 %float_0_000145526967 %float_0_00107996329 %float_n5_36151965en05 %float_0_00028339462 %float_n0_00169270835 %float_n0_00126378681 %float_n0_000513174047 %float_n0_000160845593 %float_n0_00187653187 %float_n0_000834865205 %float_0_00063572306 %float_7_65931418en06 %float_n0_00190716912 %float_n0_000222120099 %float_0_000375306379 %float_n0_00173866423 %float_n0_000405943632 %float_n0_00123314955 %float_0_00170802698 %float_n0_00094209559 %float_0_000819546578 %float_0_00184589461 %float_0_000467218139 + %uint_1 = OpConstant %uint 1 + %uint_16 = OpConstant %uint 16 + %uint_0 = OpConstant %uint 0 +%_ptr_Function__arr_float_uint_256 = OpTypePointer Function %_arr_float_uint_256 +%_ptr_Function_float = OpTypePointer Function %float + %v4float = OpTypeVector %float 4 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input + %v2float = OpTypeVector %float 2 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 +%XeBilinearConstants = OpTypeStruct %v2int %v2float +%_ptr_PushConstant_XeBilinearConstants = OpTypePointer PushConstant %XeBilinearConstants + %_ = OpVariable %_ptr_PushConstant_XeBilinearConstants PushConstant + %int_0 = OpConstant %int 0 +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output + %315 = OpTypeImage %float 2D 0 0 0 1 Unknown + %316 = OpTypeSampledImage %315 +%_ptr_UniformConstant_316 = OpTypePointer UniformConstant %316 + %xe_texture = OpVariable %_ptr_UniformConstant_316 UniformConstant + %float_0_5 = OpConstant %float 0.5 + %int_1 = OpConstant %int 1 +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %float_0 = OpConstant %float 0 + %v3float = OpTypeVector %float 3 +%_ptr_Output_float = OpTypePointer Output %float + %uint_2 = OpConstant %uint 2 + %349 = OpConstantComposite %v3float %float_0 %float_0 %float_0 + %float_1 = OpConstant %float 1 + %351 = OpConstantComposite %v3float %float_1 %float_1 %float_1 + %uint_3 = OpConstant %uint 3 + %377 = OpConstantComposite %v2float %float_0_5 %float_0_5 + %378 = OpConstantComposite %v2uint %uint_15 %uint_15 + %main = OpFunction %void None %3 + %5 = OpLabel + %361 = OpVariable %_ptr_Function__arr_float_uint_256 Function + %299 = OpLoad %v4float %gl_FragCoord + %300 = OpVectorShuffle %v2float %299 %299 0 1 + %303 = OpConvertFToS %v2int %300 + %309 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %310 = OpLoad %v2int %309 + %311 = OpISub %v2int %303 %310 + %312 = OpBitcast %v2uint %311 + %319 = OpLoad %316 %xe_texture + %321 = OpConvertUToF %v2float %312 + %324 = OpFAdd %v2float %321 %377 + %327 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_1 + %328 = OpLoad %v2float %327 + %329 = OpFMul %v2float %324 %328 + %331 = OpImageSampleExplicitLod %v4float %319 %329 Lod %float_0 + %335 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + %336 = OpCompositeExtract %float %331 0 + OpStore %335 %336 + %337 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + %338 = OpCompositeExtract %float %331 1 + OpStore %337 %338 + %340 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + %341 = OpCompositeExtract %float %331 2 + OpStore %340 %341 + %342 = OpLoad %v4float %xe_frag_color + %343 = OpVectorShuffle %v3float %342 %342 0 1 2 + %366 = OpBitwiseAnd %v2uint %312 %378 + %368 = OpCompositeExtract %uint %366 1 + %369 = OpIMul %uint %368 %uint_16 + %371 = OpCompositeExtract %uint %366 0 + %372 = OpIAdd %uint %369 %371 + OpStore %361 %276 + %373 = OpAccessChain %_ptr_Function_float %361 %372 + %374 = OpLoad %float %373 + %347 = OpCompositeConstruct %v3float %374 %374 %374 + %348 = OpFAdd %v3float %343 %347 + %352 = OpExtInst %v3float %1 FClamp %348 %349 %351 + %354 = OpCompositeExtract %float %352 0 + OpStore %335 %354 + %356 = OpCompositeExtract %float %352 1 + OpStore %337 %356 + %358 = OpCompositeExtract %float %352 2 + OpStore %340 %358 + %360 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %360 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.h new file mode 100644 index 000000000..8cae0a384 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.h @@ -0,0 +1,132 @@ +// generated from `xb genspirv` +// source: guest_output_bilinear.frag +const uint8_t guest_output_bilinear_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, + 0x72, 0x61, 0x67, 0x43, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x58, 0x65, 0x42, 0x69, + 0x6C, 0x69, 0x6E, 0x65, 0x61, 0x72, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, + 0x6E, 0x74, 0x73, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x62, 0x69, 0x6C, 0x69, 0x6E, + 0x65, 0x61, 0x72, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x62, + 0x69, 0x6C, 0x69, 0x6E, 0x65, 0x61, 0x72, 0x5F, 0x6F, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, 0x6E, 0x76, 0x00, + 0x05, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, + 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0x2B, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x3F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.spv new file mode 100644 index 000000000..c6918785d Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.txt new file mode 100644 index 000000000..4a75c3666 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.txt @@ -0,0 +1,90 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 64 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeBilinearConstants "XeBilinearConstants" + OpMemberName %XeBilinearConstants 0 "xe_bilinear_output_offset" + OpMemberName %XeBilinearConstants 1 "xe_bilinear_output_size_inv" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpName %xe_texture "xe_texture" + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeBilinearConstants 0 Offset 16 + OpMemberDecorate %XeBilinearConstants 1 Offset 24 + OpDecorate %XeBilinearConstants Block + OpDecorate %xe_frag_color Location 0 + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input + %v2float = OpTypeVector %float 2 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 +%XeBilinearConstants = OpTypeStruct %v2int %v2float +%_ptr_PushConstant_XeBilinearConstants = OpTypePointer PushConstant %XeBilinearConstants + %_ = OpVariable %_ptr_PushConstant_XeBilinearConstants PushConstant + %int_0 = OpConstant %int 0 +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output + %31 = OpTypeImage %float 2D 0 0 0 1 Unknown + %32 = OpTypeSampledImage %31 +%_ptr_UniformConstant_32 = OpTypePointer UniformConstant %32 + %xe_texture = OpVariable %_ptr_UniformConstant_32 UniformConstant + %float_0_5 = OpConstant %float 0.5 + %int_1 = OpConstant %int 1 +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %float_0 = OpConstant %float 0 + %uint_0 = OpConstant %uint 0 +%_ptr_Output_float = OpTypePointer Output %float + %uint_1 = OpConstant %uint 1 + %uint_2 = OpConstant %uint 2 + %float_1 = OpConstant %float 1 + %uint_3 = OpConstant %uint 3 + %63 = OpConstantComposite %v2float %float_0_5 %float_0_5 + %main = OpFunction %void None %3 + %5 = OpLabel + %15 = OpLoad %v4float %gl_FragCoord + %16 = OpVectorShuffle %v2float %15 %15 0 1 + %19 = OpConvertFToS %v2int %16 + %25 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %26 = OpLoad %v2int %25 + %27 = OpISub %v2int %19 %26 + %28 = OpBitcast %v2uint %27 + %35 = OpLoad %32 %xe_texture + %37 = OpConvertUToF %v2float %28 + %40 = OpFAdd %v2float %37 %63 + %43 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_1 + %44 = OpLoad %v2float %43 + %45 = OpFMul %v2float %40 %44 + %47 = OpImageSampleExplicitLod %v4float %35 %45 Lod %float_0 + %52 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + %53 = OpCompositeExtract %float %47 0 + OpStore %52 %53 + %55 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + %56 = OpCompositeExtract %float %47 1 + OpStore %55 %56 + %58 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + %59 = OpCompositeExtract %float %47 2 + OpStore %58 %59 + %62 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %62 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h new file mode 100644 index 000000000..aa976c79f --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h @@ -0,0 +1,1221 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_cas_resample_dither.frag +const uint8_t guest_output_ffx_cas_resample_dither_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x86, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x58, 0x65, 0x43, 0x61, 0x73, 0x52, 0x65, 0x73, + 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, + 0x74, 0x73, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x6F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x69, + 0x6E, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, + 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x00, 0x00, + 0x06, 0x00, 0x0A, 0x00, 0xB8, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x70, + 0x6E, 0x65, 0x73, 0x73, 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x73, 0x65, + 0x74, 0x75, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xAB, 0x01, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xAB, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xB4, 0x09, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xB8, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x1C, 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xE7, 0xE6, 0x66, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, + 0xDE, 0xDD, 0xDD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x9F, 0x9E, 0x1E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x57, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xB6, 0xB5, 0xB5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, + 0xB2, 0xB1, 0xB1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5A, 0x00, 0x00, 0x00, 0x87, 0x86, 0x06, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0xA0, 0x9F, 0x9F, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0xD2, 0xD1, 0xD1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5D, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x95, 0x94, 0x94, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x92, 0x91, 0x91, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xBE, 0xBD, 0xBD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, + 0x8F, 0x8E, 0x0E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x63, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, + 0xE5, 0xE4, 0xE4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, 0x8A, 0x89, 0x89, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0xA3, 0xA2, 0x22, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, + 0xFD, 0xFC, 0xFC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x69, 0x00, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, 0x90, 0x8F, 0x8F, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, + 0xD1, 0xD0, 0xD0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6C, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, + 0xFE, 0xFD, 0xFD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6F, 0x00, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, + 0xBB, 0xBA, 0x3A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x90, 0x8F, 0x8F, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x9D, 0x9C, 0x9C, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x75, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, + 0xC2, 0xC1, 0xC1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0xCF, 0xCE, 0x4E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, + 0xF0, 0xEF, 0xEF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7B, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x82, 0x81, 0x81, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, + 0x9A, 0x99, 0x99, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xD0, 0xCF, 0xCF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x81, 0x00, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0xF4, 0xF3, 0xF3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, + 0xE8, 0xE7, 0xE7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0xEB, 0xEA, 0x6A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, + 0xA9, 0xA8, 0x28, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x87, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xC8, 0xC7, 0xC7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, + 0xAB, 0xAA, 0x2A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, 0xD3, 0xD2, 0x52, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, + 0xC0, 0xBF, 0xBF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8D, 0x00, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0xDF, 0xDE, 0x5E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xDF, 0xDE, 0x5E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x99, 0x98, 0x18, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x9B, 0x9A, 0x1A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x96, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0xD2, 0xD1, 0xD1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x86, 0x85, 0x85, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0xD9, 0xD8, 0x58, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0xD0, 0xCF, 0xCF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9C, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00, 0x91, 0x90, 0x90, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, + 0xDD, 0xDC, 0xDC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9F, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0xB4, 0xB3, 0xB3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, + 0xF3, 0xF2, 0x72, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA2, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x9C, 0x9B, 0x9B, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, + 0xBE, 0xBD, 0xBD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA5, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, 0xF8, 0xF7, 0xF7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, + 0xC7, 0xC6, 0x46, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA8, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 0xFC, 0xFB, 0xFB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, + 0xDA, 0xD9, 0xD9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAB, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, + 0xF4, 0xF3, 0xF3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, + 0xB4, 0xB3, 0xB3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB1, 0x00, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xF1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, + 0xBF, 0xBE, 0x3E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB4, 0x00, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0xEE, 0xED, 0xED, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, + 0x96, 0x95, 0x95, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB7, 0x00, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0xD1, 0xD0, 0xD0, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, + 0xC3, 0xC2, 0x42, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBA, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x91, 0x90, 0x90, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0xC4, 0xC3, 0xC3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBD, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFB, 0xFA, 0x7A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, + 0xFE, 0xFD, 0xFD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0xE1, 0xE0, 0x60, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, + 0xA4, 0xA3, 0xA3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC3, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, + 0x81, 0x80, 0x00, 0xB7, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0xE6, 0xE5, 0xE5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC9, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, 0x9C, 0x9B, 0x9B, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, + 0xCB, 0xCA, 0x4A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, + 0xC2, 0xC1, 0xC1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCF, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0xCB, 0xCA, 0x4A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, + 0xAC, 0xAB, 0xAB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD2, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, 0xFB, 0xFA, 0x7A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, + 0xF5, 0xF4, 0xF4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD5, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, + 0xB3, 0xB2, 0x32, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD8, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, + 0xDD, 0xDC, 0xDC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDB, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, + 0xA3, 0xA2, 0x22, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, + 0xE2, 0xE1, 0xE1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE1, 0x00, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xE7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0xCF, 0xCE, 0x4E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE4, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x32, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, + 0x82, 0x81, 0x81, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE7, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, + 0xC6, 0xC5, 0xC5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0xAF, 0xAE, 0x2E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xED, 0x00, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x98, 0x97, 0x97, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, + 0xED, 0xEC, 0xEC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, + 0xC4, 0xC3, 0xC3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF3, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0xB1, 0xB0, 0xB0, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, + 0xF8, 0xF7, 0xF7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF6, 0x00, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, 0x93, 0x92, 0x12, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, + 0xF1, 0xF0, 0xF0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF9, 0x00, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, + 0xFF, 0xFE, 0x7E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xC7, 0xC6, 0x46, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xC0, 0xBF, 0xBF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0xE3, 0xE2, 0x62, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x01, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x8F, 0x8E, 0x0E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, + 0x94, 0x93, 0x93, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x05, 0x01, 0x00, 0x00, 0x85, 0x84, 0x84, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x93, 0x92, 0x12, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, + 0xEE, 0xED, 0xED, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x08, 0x01, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x98, 0x97, 0x97, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, + 0xC3, 0xC2, 0x42, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0B, 0x01, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, 0xF1, 0xF0, 0xF0, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, + 0xA0, 0x9F, 0x9F, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0E, 0x01, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, 0xC1, 0xC0, 0xC0, 0x37, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, + 0xFC, 0xFB, 0xFB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x11, 0x01, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0xBB, 0xBA, 0x3A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, + 0xCC, 0xCB, 0xCB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0xA2, 0xA1, 0xA1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, + 0xD9, 0xD8, 0x58, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x17, 0x01, 0x00, 0x00, 0x8A, 0x89, 0x89, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xBF, 0xBE, 0x3E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0xD6, 0xD5, 0xD5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1A, 0x01, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, 0xFD, 0xFC, 0xFC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, + 0xEC, 0xEB, 0xEB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1D, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1E, 0x01, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, + 0xB7, 0xB6, 0x36, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x00, 0x00, 0x86, 0x85, 0x85, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, + 0xC1, 0xC0, 0xC0, 0xB7, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x23, 0x01, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0xD3, 0xD2, 0x52, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, + 0xEB, 0xEA, 0x6A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x26, 0x01, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x9F, 0x9E, 0x1E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, + 0xB1, 0xB0, 0xB0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x29, 0x01, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, + 0xB8, 0xB7, 0xB7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2D, 0x01, 0x00, 0x00, 0xC6, 0xC5, 0xC5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, + 0xD7, 0xD6, 0x56, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2F, 0x01, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x85, 0x84, 0x84, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, + 0xC8, 0xC7, 0xC7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x32, 0x01, 0x00, 0x00, 0x94, 0x93, 0x93, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, + 0xCD, 0xCC, 0xCC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x35, 0x01, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0xB6, 0xB5, 0xB5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, + 0x92, 0x91, 0x91, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x38, 0x01, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0xE7, 0xE6, 0x66, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x99, 0x98, 0x18, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3B, 0x01, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, 0xE1, 0xE0, 0x60, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3D, 0x01, 0x00, 0x00, + 0x95, 0x94, 0x94, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3E, 0x01, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3F, 0x01, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, + 0x87, 0x86, 0x06, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x41, 0x01, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, + 0xDB, 0xDA, 0x5A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x44, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x81, 0x80, 0x00, 0x37, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, + 0xFA, 0xF9, 0xF9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x47, 0x01, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, + 0xE4, 0xE3, 0xE3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4B, 0x01, 0x00, 0x00, 0xA2, 0xA1, 0xA1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x00, + 0xE0, 0xDF, 0xDF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4D, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x00, 0x00, 0xD7, 0xD6, 0x56, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, + 0xF2, 0xF1, 0xF1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x50, 0x01, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0x39, 0x2C, 0x00, 0x03, 0x01, + 0x50, 0x00, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0x5B, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, + 0x5E, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0x6A, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x6D, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, + 0x8B, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x91, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, + 0x9D, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, + 0xA0, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, + 0xA6, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, + 0xA9, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0xAF, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0xC4, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, + 0xCA, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0xCD, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, + 0xD0, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xD3, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, + 0xD6, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, + 0xD9, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, + 0xDC, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, + 0xDF, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, + 0xE2, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, + 0xE5, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0xE8, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, + 0xEB, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0xF1, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, + 0xF4, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, + 0xF7, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, + 0x06, 0x01, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x09, 0x01, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, + 0x0C, 0x01, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, + 0x12, 0x01, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x15, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, + 0x18, 0x01, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, + 0x1B, 0x01, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x1D, 0x01, 0x00, 0x00, + 0x1E, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0x21, 0x01, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, + 0x27, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x2D, 0x01, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, + 0x33, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0x36, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, + 0x39, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, + 0x3C, 0x01, 0x00, 0x00, 0x3D, 0x01, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, + 0x3F, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, + 0x42, 0x01, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, + 0x45, 0x01, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, + 0x48, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, + 0x4B, 0x01, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x00, 0x4D, 0x01, 0x00, 0x00, + 0x4E, 0x01, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x55, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x5B, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, + 0x39, 0x46, 0xBC, 0x1F, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA1, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x09, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0xA9, 0x01, 0x00, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xAA, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xA9, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xAA, 0x01, 0x00, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xDB, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xE5, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xEB, 0x01, 0x00, 0x00, + 0xC7, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xF7, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xF6, 0x03, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, + 0x20, 0x00, 0x04, 0x00, 0xB3, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xB3, 0x09, 0x00, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x05, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xB9, 0x09, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB8, 0x09, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xB9, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xBB, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xC1, 0x09, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0x20, 0x00, 0x04, 0x00, 0xD2, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xE0, 0x09, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xE0, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xEF, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x05, 0x0A, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x06, 0x0A, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0E, 0x0A, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x75, 0x1A, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, + 0xC5, 0x09, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x85, 0x1A, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x5B, 0x01, 0x00, 0x00, + 0xB1, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xB5, 0x09, 0x00, 0x00, 0xB4, 0x09, 0x00, 0x00, + 0x4F, 0x00, 0x07, 0x00, 0x9E, 0x03, 0x00, 0x00, 0xB6, 0x09, 0x00, 0x00, + 0xB5, 0x09, 0x00, 0x00, 0xB5, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xB7, 0x09, 0x00, 0x00, 0xB6, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xBB, 0x09, 0x00, 0x00, 0xBC, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xBD, 0x09, 0x00, 0x00, 0xBC, 0x09, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xBE, 0x09, 0x00, 0x00, 0xB7, 0x09, 0x00, 0x00, + 0xBD, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xBF, 0x09, 0x00, 0x00, 0xBE, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC1, 0x09, 0x00, 0x00, 0xC2, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0xC3, 0x09, 0x00, 0x00, 0xC2, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x00, 0xC3, 0x09, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x9E, 0x03, 0x00, 0x00, 0xC8, 0x09, 0x00, 0x00, + 0xC3, 0x09, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0xCA, 0x09, 0x00, 0x00, 0xC8, 0x09, 0x00, 0x00, + 0x75, 0x1A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xCB, 0x09, 0x00, 0x00, 0xCA, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xD2, 0x09, 0x00, 0x00, 0xD3, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD4, 0x09, 0x00, 0x00, 0xD3, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD5, 0x09, 0x00, 0x00, 0xD4, 0x09, 0x00, 0x00, + 0xF9, 0x00, 0x02, 0x00, 0x09, 0x0C, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0x09, 0x0C, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x68, 0x0D, 0x00, 0x00, 0xBF, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x6E, 0x0D, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x6F, 0x0D, 0x00, 0x00, + 0x68, 0x0D, 0x00, 0x00, 0x6E, 0x0D, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, 0xCB, 0x09, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x76, 0x0D, 0x00, 0x00, + 0x6F, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x78, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x76, 0x0D, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x7B, 0x0D, 0x00, 0x00, 0x76, 0x0D, 0x00, 0x00, + 0x78, 0x0D, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x7D, 0x0D, 0x00, 0x00, 0x78, 0x0D, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x82, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, + 0xCE, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xA9, 0x01, 0x00, 0x00, + 0xB8, 0x13, 0x00, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xBA, 0x13, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xBB, 0x13, 0x00, 0x00, + 0xBA, 0x13, 0x00, 0x00, 0x82, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x85, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, 0xDB, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xC1, 0x13, 0x00, 0x00, + 0xB8, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xC2, 0x13, 0x00, 0x00, 0xC1, 0x13, 0x00, 0x00, 0x85, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xC8, 0x13, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xC9, 0x13, 0x00, 0x00, + 0xC8, 0x13, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x8A, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xCF, 0x13, 0x00, 0x00, + 0xB8, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xD0, 0x13, 0x00, 0x00, 0xCF, 0x13, 0x00, 0x00, 0x8A, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x90, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, + 0xE5, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xDD, 0x13, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xDE, 0x13, 0x00, 0x00, 0xDD, 0x13, 0x00, 0x00, + 0x90, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x93, 0x0D, 0x00, 0x00, + 0x7D, 0x0D, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xE4, 0x13, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xE5, 0x13, 0x00, 0x00, + 0xE4, 0x13, 0x00, 0x00, 0x93, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x96, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, 0xEB, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xEB, 0x13, 0x00, 0x00, + 0xB8, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xEC, 0x13, 0x00, 0x00, 0xEB, 0x13, 0x00, 0x00, 0x96, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x99, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, + 0xF1, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xF2, 0x13, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xF3, 0x13, 0x00, 0x00, 0xF2, 0x13, 0x00, 0x00, + 0x99, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x9F, 0x0D, 0x00, 0x00, + 0x7D, 0x0D, 0x00, 0x00, 0xF6, 0x03, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x9F, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xA2, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, 0xF7, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0x07, 0x14, 0x00, 0x00, + 0xB8, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0x08, 0x14, 0x00, 0x00, 0x07, 0x14, 0x00, 0x00, 0xA2, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xA5, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0x0E, 0x14, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0x0F, 0x14, 0x00, 0x00, 0x0E, 0x14, 0x00, 0x00, + 0xA5, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xA8, 0x0D, 0x00, 0x00, + 0x7D, 0x0D, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0x15, 0x14, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x16, 0x14, 0x00, 0x00, + 0x15, 0x14, 0x00, 0x00, 0xA8, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBB, 0x0D, 0x00, 0x00, 0xBB, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBD, 0x0D, 0x00, 0x00, + 0xBB, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBF, 0x0D, 0x00, 0x00, 0xBB, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2C, 0x14, 0x00, 0x00, 0xBB, 0x0D, 0x00, 0x00, 0xBB, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2F, 0x14, 0x00, 0x00, + 0xBD, 0x0D, 0x00, 0x00, 0xBD, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x32, 0x14, 0x00, 0x00, 0xBF, 0x0D, 0x00, 0x00, + 0xBF, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC8, 0x0D, 0x00, 0x00, 0xD0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCA, 0x0D, 0x00, 0x00, + 0xD0, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCC, 0x0D, 0x00, 0x00, 0xD0, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x36, 0x14, 0x00, 0x00, 0xC8, 0x0D, 0x00, 0x00, 0xC8, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x39, 0x14, 0x00, 0x00, + 0xCA, 0x0D, 0x00, 0x00, 0xCA, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3C, 0x14, 0x00, 0x00, 0xCC, 0x0D, 0x00, 0x00, + 0xCC, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE2, 0x0D, 0x00, 0x00, 0xC2, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE4, 0x0D, 0x00, 0x00, + 0xC2, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE6, 0x0D, 0x00, 0x00, 0xC2, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4A, 0x14, 0x00, 0x00, 0xE2, 0x0D, 0x00, 0x00, 0xE2, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4D, 0x14, 0x00, 0x00, + 0xE4, 0x0D, 0x00, 0x00, 0xE4, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, 0xE6, 0x0D, 0x00, 0x00, + 0xE6, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEF, 0x0D, 0x00, 0x00, 0xC9, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF1, 0x0D, 0x00, 0x00, + 0xC9, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF3, 0x0D, 0x00, 0x00, 0xC9, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x54, 0x14, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x57, 0x14, 0x00, 0x00, + 0xF1, 0x0D, 0x00, 0x00, 0xF1, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, 0xF3, 0x0D, 0x00, 0x00, + 0xF3, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFC, 0x0D, 0x00, 0x00, 0xDE, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFE, 0x0D, 0x00, 0x00, + 0xDE, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0xDE, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5E, 0x14, 0x00, 0x00, 0xFC, 0x0D, 0x00, 0x00, 0xFC, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x61, 0x14, 0x00, 0x00, + 0xFE, 0x0D, 0x00, 0x00, 0xFE, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x64, 0x14, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x0E, 0x00, 0x00, 0xE5, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0B, 0x0E, 0x00, 0x00, + 0xE5, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0D, 0x0E, 0x00, 0x00, 0xE5, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x68, 0x14, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6B, 0x14, 0x00, 0x00, + 0x0B, 0x0E, 0x00, 0x00, 0x0B, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6E, 0x14, 0x00, 0x00, 0x0D, 0x0E, 0x00, 0x00, + 0x0D, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x16, 0x0E, 0x00, 0x00, 0xEC, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x18, 0x0E, 0x00, 0x00, + 0xEC, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1A, 0x0E, 0x00, 0x00, 0xEC, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x72, 0x14, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x75, 0x14, 0x00, 0x00, + 0x18, 0x0E, 0x00, 0x00, 0x18, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x78, 0x14, 0x00, 0x00, 0x1A, 0x0E, 0x00, 0x00, + 0x1A, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x23, 0x0E, 0x00, 0x00, 0xF3, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x25, 0x0E, 0x00, 0x00, + 0xF3, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x27, 0x0E, 0x00, 0x00, 0xF3, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7C, 0x14, 0x00, 0x00, 0x23, 0x0E, 0x00, 0x00, 0x23, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7F, 0x14, 0x00, 0x00, + 0x25, 0x0E, 0x00, 0x00, 0x25, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x82, 0x14, 0x00, 0x00, 0x27, 0x0E, 0x00, 0x00, + 0x27, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x30, 0x0E, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x32, 0x0E, 0x00, 0x00, + 0x08, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x34, 0x0E, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x86, 0x14, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x89, 0x14, 0x00, 0x00, + 0x32, 0x0E, 0x00, 0x00, 0x32, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8C, 0x14, 0x00, 0x00, 0x34, 0x0E, 0x00, 0x00, + 0x34, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3D, 0x0E, 0x00, 0x00, 0x0F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3F, 0x0E, 0x00, 0x00, + 0x0F, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x00, 0x00, 0x0F, 0x14, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x90, 0x14, 0x00, 0x00, 0x3D, 0x0E, 0x00, 0x00, 0x3D, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x14, 0x00, 0x00, + 0x3F, 0x0E, 0x00, 0x00, 0x3F, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x96, 0x14, 0x00, 0x00, 0x41, 0x0E, 0x00, 0x00, + 0x41, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x57, 0x0E, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x59, 0x0E, 0x00, 0x00, + 0x01, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x0E, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA4, 0x14, 0x00, 0x00, 0x57, 0x0E, 0x00, 0x00, 0x57, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA7, 0x14, 0x00, 0x00, + 0x59, 0x0E, 0x00, 0x00, 0x59, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAA, 0x14, 0x00, 0x00, 0x5B, 0x0E, 0x00, 0x00, + 0x5B, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x64, 0x0E, 0x00, 0x00, 0x16, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x0E, 0x00, 0x00, + 0x16, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x68, 0x0E, 0x00, 0x00, 0x16, 0x14, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAE, 0x14, 0x00, 0x00, 0x64, 0x0E, 0x00, 0x00, 0x64, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB1, 0x14, 0x00, 0x00, + 0x66, 0x0E, 0x00, 0x00, 0x66, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB4, 0x14, 0x00, 0x00, 0x68, 0x0E, 0x00, 0x00, + 0x68, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD2, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x4D, 0x14, 0x00, 0x00, 0x57, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD3, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x2F, 0x14, 0x00, 0x00, 0xD2, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD9, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x61, 0x14, 0x00, 0x00, + 0x7F, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDA, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xD3, 0x14, 0x00, 0x00, 0xD9, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x4D, 0x14, 0x00, 0x00, 0x57, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFD, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2F, 0x14, 0x00, 0x00, + 0xFC, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x61, 0x14, 0x00, 0x00, 0x7F, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xFD, 0x14, 0x00, 0x00, 0x03, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x57, 0x14, 0x00, 0x00, + 0x61, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x27, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x39, 0x14, 0x00, 0x00, 0x26, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2D, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x6B, 0x14, 0x00, 0x00, 0x89, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x15, 0x00, 0x00, + 0x2D, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x50, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x57, 0x14, 0x00, 0x00, 0x61, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x51, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x39, 0x14, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x57, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x6B, 0x14, 0x00, 0x00, + 0x89, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x58, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x51, 0x15, 0x00, 0x00, 0x57, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7A, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x75, 0x14, 0x00, 0x00, 0x7F, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x57, 0x14, 0x00, 0x00, + 0x7A, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x81, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x89, 0x14, 0x00, 0x00, 0xA7, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x82, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x7B, 0x15, 0x00, 0x00, 0x81, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x75, 0x14, 0x00, 0x00, + 0x7F, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA5, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x57, 0x14, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAB, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x89, 0x14, 0x00, 0x00, 0xA7, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAC, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xA5, 0x15, 0x00, 0x00, + 0xAB, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCE, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x7F, 0x14, 0x00, 0x00, 0x89, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCF, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x61, 0x14, 0x00, 0x00, 0xCE, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD5, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x93, 0x14, 0x00, 0x00, + 0xB1, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD6, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xCF, 0x15, 0x00, 0x00, 0xD5, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x7F, 0x14, 0x00, 0x00, 0x89, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x61, 0x14, 0x00, 0x00, + 0xF8, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFF, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x93, 0x14, 0x00, 0x00, 0xB1, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0xFF, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x16, 0x00, 0x00, + 0x04, 0x15, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x1F, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x21, 0x16, 0x00, 0x00, + 0x20, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x40, 0x16, 0x00, 0x00, 0x58, 0x15, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x41, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x40, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x42, 0x16, 0x00, 0x00, 0x41, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x61, 0x16, 0x00, 0x00, 0xAC, 0x15, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x16, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x61, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x63, 0x16, 0x00, 0x00, 0x62, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x82, 0x16, 0x00, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x83, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x82, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x16, 0x00, 0x00, + 0x83, 0x16, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC0, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC1, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xDA, 0x14, 0x00, 0x00, + 0xC0, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC3, 0x0F, 0x00, 0x00, 0xC1, 0x0F, 0x00, 0x00, 0x21, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAE, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xC3, 0x0F, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD8, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x58, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD9, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x2E, 0x15, 0x00, 0x00, 0xD8, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDB, 0x0F, 0x00, 0x00, 0xD9, 0x0F, 0x00, 0x00, + 0x42, 0x16, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE1, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xDB, 0x0F, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0xAC, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF1, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x82, 0x15, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x00, 0x00, + 0xF1, 0x0F, 0x00, 0x00, 0x63, 0x16, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x14, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x08, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xD6, 0x15, 0x00, 0x00, + 0x08, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0B, 0x10, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x84, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x47, 0x17, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x0B, 0x10, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x75, 0x17, 0x00, 0x00, 0xAE, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x17, 0x00, 0x00, + 0x75, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x79, 0x17, 0x00, 0x00, 0x77, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7A, 0x17, 0x00, 0x00, 0x79, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA8, 0x17, 0x00, 0x00, 0xE1, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAA, 0x17, 0x00, 0x00, + 0xA8, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAC, 0x17, 0x00, 0x00, 0xAA, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAD, 0x17, 0x00, 0x00, 0xAC, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDB, 0x17, 0x00, 0x00, 0x14, 0x17, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDD, 0x17, 0x00, 0x00, + 0xDB, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDF, 0x17, 0x00, 0x00, 0xDD, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE0, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x18, 0x00, 0x00, 0x47, 0x17, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x18, 0x00, 0x00, + 0x0E, 0x18, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x12, 0x18, 0x00, 0x00, 0x10, 0x18, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x13, 0x18, 0x00, 0x00, 0x12, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2F, 0x10, 0x00, 0x00, 0xD5, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, + 0x7A, 0x17, 0x00, 0x00, 0x2F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3E, 0x10, 0x00, 0x00, 0xAD, 0x17, 0x00, 0x00, + 0x2F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x47, 0x10, 0x00, 0x00, 0xE0, 0x17, 0x00, 0x00, 0x2F, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, + 0x13, 0x18, 0x00, 0x00, 0x2F, 0x10, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x56, 0x10, 0x00, 0x00, 0x7B, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x57, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x56, 0x10, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5A, 0x10, 0x00, 0x00, + 0x7B, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x5A, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5C, 0x10, 0x00, 0x00, 0x57, 0x10, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, + 0x56, 0x10, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6A, 0x10, 0x00, 0x00, 0x57, 0x10, 0x00, 0x00, + 0x5A, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6F, 0x10, 0x00, 0x00, 0x56, 0x10, 0x00, 0x00, 0x5A, 0x10, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x10, 0x00, 0x00, + 0x04, 0x15, 0x00, 0x00, 0xDA, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, + 0x73, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3C, 0x18, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3D, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x3C, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3E, 0x18, 0x00, 0x00, 0x3D, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x77, 0x10, 0x00, 0x00, 0x5C, 0x10, 0x00, 0x00, + 0x3E, 0x18, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7B, 0x10, 0x00, 0x00, 0x58, 0x15, 0x00, 0x00, 0x2E, 0x15, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7C, 0x10, 0x00, 0x00, + 0x0A, 0x08, 0x00, 0x00, 0x7B, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x47, 0x18, 0x00, 0x00, 0x7C, 0x10, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x18, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x47, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x48, 0x18, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7F, 0x10, 0x00, 0x00, + 0x63, 0x10, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, 0xAC, 0x15, 0x00, 0x00, + 0x82, 0x15, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x84, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x18, 0x00, 0x00, + 0x84, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x53, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x52, 0x18, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x18, 0x00, 0x00, + 0x53, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x87, 0x10, 0x00, 0x00, 0x6A, 0x10, 0x00, 0x00, 0x54, 0x18, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8B, 0x10, 0x00, 0x00, + 0x00, 0x16, 0x00, 0x00, 0xD6, 0x15, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8C, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, + 0x8B, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5D, 0x18, 0x00, 0x00, 0x8C, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5E, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x5D, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5F, 0x18, 0x00, 0x00, 0x5E, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8F, 0x10, 0x00, 0x00, 0x6F, 0x10, 0x00, 0x00, + 0x5F, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x95, 0x10, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x77, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9E, 0x10, 0x00, 0x00, + 0x3E, 0x10, 0x00, 0x00, 0x7F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, 0x47, 0x10, 0x00, 0x00, + 0x87, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB1, 0x10, 0x00, 0x00, 0x9E, 0x10, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, + 0xB1, 0x10, 0x00, 0x00, 0x77, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCB, 0x10, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, + 0x8F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCC, 0x10, 0x00, 0x00, 0x95, 0x10, 0x00, 0x00, 0xCB, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCE, 0x10, 0x00, 0x00, + 0xCC, 0x10, 0x00, 0x00, 0x7F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE9, 0x10, 0x00, 0x00, 0xCC, 0x10, 0x00, 0x00, + 0x87, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x04, 0x11, 0x00, 0x00, 0xB1, 0x10, 0x00, 0x00, 0x8F, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x76, 0x1A, 0x00, 0x00, + 0x95, 0x10, 0x00, 0x00, 0x9E, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x77, 0x1A, 0x00, 0x00, 0x76, 0x1A, 0x00, 0x00, + 0xB0, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x1A, 0x00, 0x00, 0x77, 0x1A, 0x00, 0x00, 0xCB, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x11, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x78, 0x1A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x11, 0x00, 0x00, 0x2E, 0x11, 0x00, 0x00, + 0xB3, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x32, 0x11, 0x00, 0x00, 0x30, 0x11, 0x00, 0x00, 0xCE, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x34, 0x11, 0x00, 0x00, + 0x32, 0x11, 0x00, 0x00, 0xE9, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x34, 0x11, 0x00, 0x00, + 0x04, 0x11, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x76, 0x18, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x77, 0x18, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, + 0x76, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x18, 0x00, 0x00, 0x77, 0x18, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7B, 0x18, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7D, 0x18, 0x00, 0x00, + 0x7B, 0x18, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7F, 0x18, 0x00, 0x00, 0x7D, 0x18, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x80, 0x18, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00, 0x7F, 0x18, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x79, 0x1A, 0x00, 0x00, + 0x2C, 0x14, 0x00, 0x00, 0x4A, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x40, 0x11, 0x00, 0x00, 0x95, 0x10, 0x00, 0x00, + 0x79, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x44, 0x11, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00, 0x9E, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x45, 0x11, 0x00, 0x00, + 0x40, 0x11, 0x00, 0x00, 0x44, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x49, 0x11, 0x00, 0x00, 0x68, 0x14, 0x00, 0x00, + 0x9E, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4A, 0x11, 0x00, 0x00, 0x45, 0x11, 0x00, 0x00, 0x49, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4E, 0x11, 0x00, 0x00, + 0x72, 0x14, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4F, 0x11, 0x00, 0x00, 0x4A, 0x11, 0x00, 0x00, + 0x4E, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x53, 0x11, 0x00, 0x00, 0xA4, 0x14, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x11, 0x00, 0x00, + 0x4F, 0x11, 0x00, 0x00, 0x53, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x58, 0x11, 0x00, 0x00, 0x90, 0x14, 0x00, 0x00, + 0xCB, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x59, 0x11, 0x00, 0x00, 0x54, 0x11, 0x00, 0x00, 0x58, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5D, 0x11, 0x00, 0x00, + 0xAE, 0x14, 0x00, 0x00, 0xCB, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5E, 0x11, 0x00, 0x00, 0x59, 0x11, 0x00, 0x00, + 0x5D, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x62, 0x11, 0x00, 0x00, 0x54, 0x14, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x11, 0x00, 0x00, + 0x5E, 0x11, 0x00, 0x00, 0x62, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x67, 0x11, 0x00, 0x00, 0x5E, 0x14, 0x00, 0x00, + 0xCE, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x68, 0x11, 0x00, 0x00, 0x63, 0x11, 0x00, 0x00, 0x67, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6C, 0x11, 0x00, 0x00, + 0x7C, 0x14, 0x00, 0x00, 0xE9, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6D, 0x11, 0x00, 0x00, 0x68, 0x11, 0x00, 0x00, + 0x6C, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x11, 0x00, 0x00, 0x86, 0x14, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x11, 0x00, 0x00, + 0x6D, 0x11, 0x00, 0x00, 0x71, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x74, 0x11, 0x00, 0x00, 0x72, 0x11, 0x00, 0x00, + 0x80, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8E, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x74, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7A, 0x1A, 0x00, 0x00, + 0x2F, 0x14, 0x00, 0x00, 0x4D, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7E, 0x11, 0x00, 0x00, 0x95, 0x10, 0x00, 0x00, + 0x7A, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x82, 0x11, 0x00, 0x00, 0x39, 0x14, 0x00, 0x00, 0x9E, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x83, 0x11, 0x00, 0x00, + 0x7E, 0x11, 0x00, 0x00, 0x82, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x87, 0x11, 0x00, 0x00, 0x6B, 0x14, 0x00, 0x00, + 0x9E, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x88, 0x11, 0x00, 0x00, 0x83, 0x11, 0x00, 0x00, 0x87, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8C, 0x11, 0x00, 0x00, + 0x75, 0x14, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8D, 0x11, 0x00, 0x00, 0x88, 0x11, 0x00, 0x00, + 0x8C, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x91, 0x11, 0x00, 0x00, 0xA7, 0x14, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x92, 0x11, 0x00, 0x00, + 0x8D, 0x11, 0x00, 0x00, 0x91, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x96, 0x11, 0x00, 0x00, 0x93, 0x14, 0x00, 0x00, + 0xCB, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x97, 0x11, 0x00, 0x00, 0x92, 0x11, 0x00, 0x00, 0x96, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9B, 0x11, 0x00, 0x00, + 0xB1, 0x14, 0x00, 0x00, 0xCB, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9C, 0x11, 0x00, 0x00, 0x97, 0x11, 0x00, 0x00, + 0x9B, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA0, 0x11, 0x00, 0x00, 0x57, 0x14, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA1, 0x11, 0x00, 0x00, + 0x9C, 0x11, 0x00, 0x00, 0xA0, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA5, 0x11, 0x00, 0x00, 0x61, 0x14, 0x00, 0x00, + 0xCE, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA6, 0x11, 0x00, 0x00, 0xA1, 0x11, 0x00, 0x00, 0xA5, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAA, 0x11, 0x00, 0x00, + 0x7F, 0x14, 0x00, 0x00, 0xE9, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAB, 0x11, 0x00, 0x00, 0xA6, 0x11, 0x00, 0x00, + 0xAA, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAF, 0x11, 0x00, 0x00, 0x89, 0x14, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x11, 0x00, 0x00, + 0xAB, 0x11, 0x00, 0x00, 0xAF, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB2, 0x11, 0x00, 0x00, 0xB0, 0x11, 0x00, 0x00, + 0x80, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9C, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xB2, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x1A, 0x00, 0x00, + 0x32, 0x14, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBC, 0x11, 0x00, 0x00, 0x95, 0x10, 0x00, 0x00, + 0x7B, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC0, 0x11, 0x00, 0x00, 0x3C, 0x14, 0x00, 0x00, 0x9E, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC1, 0x11, 0x00, 0x00, + 0xBC, 0x11, 0x00, 0x00, 0xC0, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC5, 0x11, 0x00, 0x00, 0x6E, 0x14, 0x00, 0x00, + 0x9E, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC6, 0x11, 0x00, 0x00, 0xC1, 0x11, 0x00, 0x00, 0xC5, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCA, 0x11, 0x00, 0x00, + 0x78, 0x14, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCB, 0x11, 0x00, 0x00, 0xC6, 0x11, 0x00, 0x00, + 0xCA, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCF, 0x11, 0x00, 0x00, 0xAA, 0x14, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD0, 0x11, 0x00, 0x00, + 0xCB, 0x11, 0x00, 0x00, 0xCF, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD4, 0x11, 0x00, 0x00, 0x96, 0x14, 0x00, 0x00, + 0xCB, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD5, 0x11, 0x00, 0x00, 0xD0, 0x11, 0x00, 0x00, 0xD4, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD9, 0x11, 0x00, 0x00, + 0xB4, 0x14, 0x00, 0x00, 0xCB, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDA, 0x11, 0x00, 0x00, 0xD5, 0x11, 0x00, 0x00, + 0xD9, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDE, 0x11, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDF, 0x11, 0x00, 0x00, + 0xDA, 0x11, 0x00, 0x00, 0xDE, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE3, 0x11, 0x00, 0x00, 0x64, 0x14, 0x00, 0x00, + 0xCE, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE4, 0x11, 0x00, 0x00, 0xDF, 0x11, 0x00, 0x00, 0xE3, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE8, 0x11, 0x00, 0x00, + 0x82, 0x14, 0x00, 0x00, 0xE9, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE9, 0x11, 0x00, 0x00, 0xE4, 0x11, 0x00, 0x00, + 0xE8, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xED, 0x11, 0x00, 0x00, 0x8C, 0x14, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEE, 0x11, 0x00, 0x00, + 0xE9, 0x11, 0x00, 0x00, 0xED, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF0, 0x11, 0x00, 0x00, 0xEE, 0x11, 0x00, 0x00, + 0x80, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAA, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xF0, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xEF, 0x09, 0x00, 0x00, 0xF0, 0x09, 0x00, 0x00, + 0xE1, 0x09, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xF0, 0x09, 0x00, 0x00, 0x8E, 0x18, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xEF, 0x09, 0x00, 0x00, 0xF2, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x52, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xF2, 0x09, 0x00, 0x00, + 0x9C, 0x18, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xEF, 0x09, 0x00, 0x00, + 0xF4, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xF4, 0x09, 0x00, 0x00, 0xAA, 0x18, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, + 0xE1, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xF6, 0x09, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0xF7, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF9, 0x09, 0x00, 0x00, + 0xF7, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xF0, 0x09, 0x00, 0x00, 0xF9, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFB, 0x09, 0x00, 0x00, 0xF7, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xF2, 0x09, 0x00, 0x00, + 0xFB, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFD, 0x09, 0x00, 0x00, 0xF7, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xF4, 0x09, 0x00, 0x00, 0xFD, 0x09, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xFE, 0x09, 0x00, 0x00, + 0xE1, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xFF, 0x09, 0x00, 0x00, 0xFE, 0x09, 0x00, 0x00, 0xFE, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xB6, 0x18, 0x00, 0x00, + 0xBF, 0x09, 0x00, 0x00, 0x85, 0x1A, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB8, 0x18, 0x00, 0x00, 0xB6, 0x18, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB9, 0x18, 0x00, 0x00, 0xB8, 0x18, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBB, 0x18, 0x00, 0x00, + 0xB6, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBC, 0x18, 0x00, 0x00, 0xB9, 0x18, 0x00, 0x00, + 0xBB, 0x18, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xB1, 0x18, 0x00, 0x00, + 0x51, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0xBD, 0x18, 0x00, 0x00, 0xB1, 0x18, 0x00, 0x00, 0xBC, 0x18, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBE, 0x18, 0x00, 0x00, + 0xBD, 0x18, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x03, 0x0A, 0x00, 0x00, 0xBE, 0x18, 0x00, 0x00, 0xBE, 0x18, 0x00, 0x00, + 0xBE, 0x18, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x04, 0x0A, 0x00, 0x00, 0xFF, 0x09, 0x00, 0x00, 0x03, 0x0A, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, 0x07, 0x0A, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x04, 0x0A, 0x00, 0x00, + 0x05, 0x0A, 0x00, 0x00, 0x06, 0x0A, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x09, 0x0A, 0x00, 0x00, 0x07, 0x0A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xF0, 0x09, 0x00, 0x00, + 0x09, 0x0A, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0B, 0x0A, 0x00, 0x00, 0x07, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xF2, 0x09, 0x00, 0x00, 0x0B, 0x0A, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0D, 0x0A, 0x00, 0x00, + 0x07, 0x0A, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xF4, 0x09, 0x00, 0x00, 0x0D, 0x0A, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xEF, 0x09, 0x00, 0x00, 0x0F, 0x0A, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x0E, 0x0A, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x0F, 0x0A, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.spv new file mode 100644 index 000000000..baf79a005 Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.txt new file mode 100644 index 000000000..b33aefd09 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.txt @@ -0,0 +1,734 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 6790 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeCasResampleConstants "XeCasResampleConstants" + OpMemberName %XeCasResampleConstants 0 "xe_cas_output_offset" + OpMemberName %XeCasResampleConstants 1 "xe_cas_input_output_size_ratio" + OpMemberName %XeCasResampleConstants 2 "xe_cas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeCasResampleConstants 0 Offset 16 + OpMemberDecorate %XeCasResampleConstants 1 Offset 24 + OpMemberDecorate %XeCasResampleConstants 2 Offset 32 + OpDecorate %XeCasResampleConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %float = OpTypeFloat 32 +%_ptr_Function_float = OpTypePointer Function %float + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v3float = OpTypeVector %float 3 + %uint_15 = OpConstant %uint 15 + %uint_256 = OpConstant %uint 256 +%_arr_float_uint_256 = OpTypeArray %float %uint_256 +%float_n0_00100337015 = OpConstant %float -0.00100337015 +%float_0_000880821084 = OpConstant %float 0.000880821084 +%float_0_00169270835 = OpConstant %float 0.00169270835 +%float_n0_00155484071 = OpConstant %float -0.00155484071 +%float_0_00127910543 = OpConstant %float 0.00127910543 +%float_n0_000605085806 = OpConstant %float -0.000605085806 +%float_0_00106464466 = OpConstant %float 0.00106464466 +%float_n0_00138633582 = OpConstant %float -0.00138633582 +%float_0_00135569857 = OpConstant %float 0.00135569857 +%float_0_000513174047 = OpConstant %float 0.000513174047 +%float_0_00121783093 = OpConstant %float 0.00121783093 +%float_n0_00160079659 = OpConstant %float -0.00160079659 +%float_0_00058976718 = OpConstant %float 0.00058976718 +%float_n0_00028339462 = OpConstant %float -0.00028339462 +%float_0_00111060054 = OpConstant %float 0.00111060054 +%float_n0_00141697307 = OpConstant %float -0.00141697307 +%float_0_00144761032 = OpConstant %float 0.00144761032 +%float_n0_0005438113 = OpConstant %float -0.0005438113 +%float_0_00013020834 = OpConstant %float 0.00013020834 +%float_n0_0012025123 = OpConstant %float -0.0012025123 +%float_0_000436580885 = OpConstant %float 0.000436580885 +%float_n0_00104932603 = OpConstant %float -0.00104932603 +%float_0_000620404433 = OpConstant %float 0.000620404433 +%float_n0_000482536765 = OpConstant %float -0.000482536765 +%float_0_00187653187 = OpConstant %float 0.00187653187 +%float_n0_00109528191 = OpConstant %float -0.00109528191 +%float_n9_95710798en05 = OpConstant %float -9.95710798e-05 +%float_n0_000528492674 = OpConstant %float -0.000528492674 +%float_0_0014322917 = OpConstant %float 0.0014322917 +%float_n0_00193780637 = OpConstant %float -0.00193780637 +%float_n0_000696997566 = OpConstant %float -0.000696997566 +%float_3_829657en05 = OpConstant %float 3.829657e-05 +%float_0_000712316192 = OpConstant %float 0.000712316192 +%float_n0_00130974269 = OpConstant %float -0.00130974269 +%float_0_00109528191 = OpConstant %float 0.00109528191 +%float_n0_000298713247 = OpConstant %float -0.000298713247 +%float_0_00175398286 = OpConstant %float 0.00175398286 +%float_n0_00167738972 = OpConstant %float -0.00167738972 +%float_0_00147824758 = OpConstant %float 0.00147824758 +%float_n3_829657en05 = OpConstant %float -3.829657e-05 +%float_0_000788909325 = OpConstant %float 0.000788909325 +%float_n0_00183057599 = OpConstant %float -0.00183057599 +%float_0_000298713247 = OpConstant %float 0.000298713247 +%float_0_000988051528 = OpConstant %float 0.000988051528 +%float_n0_00117187505 = OpConstant %float -0.00117187505 +%float_0_00017616422 = OpConstant %float 0.00017616422 +%float_0_00164675247 = OpConstant %float 0.00164675247 +%float_n0_00158547796 = OpConstant %float -0.00158547796 +%float_0_000344669126 = OpConstant %float 0.000344669126 +%float_0_00186121324 = OpConstant %float 0.00186121324 +%float_n0_00176930148 = OpConstant %float -0.00176930148 +%float_n0_000865502458 = OpConstant %float -0.000865502458 +%float_0_000896139711 = OpConstant %float 0.000896139711 +%float_0_000160845593 = OpConstant %float 0.000160845593 +%float_n0_000926776964 = OpConstant %float -0.000926776964 +%float_n0_00152420346 = OpConstant %float -0.00152420346 +%float_n0_000651041686 = OpConstant %float -0.000651041686 +%float_0_00129442406 = OpConstant %float 0.00129442406 +%float_n0_000804227951 = OpConstant %float -0.000804227951 +%float_n0_00146292895 = OpConstant %float -0.00146292895 +%float_0_00179993873 = OpConstant %float 0.00179993873 +%float_n0_000850183831 = OpConstant %float -0.000850183831 +%float_0_000850183831 = OpConstant %float 0.000850183831 +%float_n0_000451899512 = OpConstant %float -0.000451899512 +%float_n0_00106464466 = OpConstant %float -0.00106464466 +%float_n0_000145526967 = OpConstant %float -0.000145526967 +%float_0_000237438726 = OpConstant %float 0.000237438726 +%float_0_00141697307 = OpConstant %float 0.00141697307 +%float_n0_00058976718 = OpConstant %float -0.00058976718 +%float_n0_000191482846 = OpConstant %float -0.000191482846 +%float_0_00160079659 = OpConstant %float 0.00160079659 +%float_0_00101868878 = OpConstant %float 0.00101868878 +%float_0_000405943632 = OpConstant %float 0.000405943632 +%float_n0_000206801473 = OpConstant %float -0.000206801473 +%float_0_00158547796 = OpConstant %float 0.00158547796 +%float_0_000651041686 = OpConstant %float 0.000651041686 +%float_n6_89338267en05 = OpConstant %float -6.89338267e-05 +%float_0_000421262259 = OpConstant %float 0.000421262259 +%float_n0_00164675247 = OpConstant %float -0.00164675247 +%float_0_00137101719 = OpConstant %float 0.00137101719 +%float_0_000926776964 = OpConstant %float 0.000926776964 +%float_n0_000666360313 = OpConstant %float -0.000666360313 +%float_0_00118719367 = OpConstant %float 0.00118719367 +%float_n0_00144761032 = OpConstant %float -0.00144761032 +%float_0_000574448553 = OpConstant %float 0.000574448553 +%float_n0_00189185049 = OpConstant %float -0.00189185049 +%float_0_000758272072 = OpConstant %float 0.000758272072 +%float_n0_00129442406 = OpConstant %float -0.00129442406 +%float_0_00192248775 = OpConstant %float 0.00192248775 +%float_n0_0016620711 = OpConstant %float -0.0016620711 +%float_n0_00103400741 = OpConstant %float -0.00103400741 +%float_n0_000497855421 = OpConstant %float -0.000497855421 +%float_n0_00186121324 = OpConstant %float -0.00186121324 +%float_0_0012025123 = OpConstant %float 0.0012025123 +%float_n0_0003293505 = OpConstant %float -0.0003293505 +%float_n0_00137101719 = OpConstant %float -0.00137101719 +%float_0_00163143384 = OpConstant %float 0.00163143384 +%float_n0_00184589461 = OpConstant %float -0.00184589461 +%float_0_000727634819 = OpConstant %float 0.000727634819 +%float_n0_000911458337 = OpConstant %float -0.000911458337 +%float_0_00181525736 = OpConstant %float 0.00181525736 +%float_n0_00114123779 = OpConstant %float -0.00114123779 +%float_n0_000375306379 = OpConstant %float -0.000375306379 +%float_9_95710798en05 = OpConstant %float 9.95710798e-05 +%float_n0_000742953445 = OpConstant %float -0.000742953445 +%float_0_00117187505 = OpConstant %float 0.00117187505 +%float_6_89338267en05 = OpConstant %float 6.89338267e-05 +%float_0_0014935662 = OpConstant %float 0.0014935662 +%float_0_000972732843 = OpConstant %float 0.000972732843 +%float_n0_000957414217 = OpConstant %float -0.000957414217 +%float_0_00193780637 = OpConstant %float 0.00193780637 +%float_0_000528492674 = OpConstant %float 0.000528492674 +%float_5_36151965en05 = OpConstant %float 5.36151965e-05 +%float_n0_00124846818 = OpConstant %float -0.00124846818 +%float_n0_000268075994 = OpConstant %float -0.000268075994 +%float_0_00153952208 = OpConstant %float 0.00153952208 +%float_n7_65931418en06 = OpConstant %float -7.65931418e-06 +%float_0_000314031873 = OpConstant %float 0.000314031873 +%float_0_00134037994 = OpConstant %float 0.00134037994 +%float_n0_00175398286 = OpConstant %float -0.00175398286 +%float_0_000497855421 = OpConstant %float 0.000497855421 +%float_n0_00118719367 = OpConstant %float -0.00118719367 +%float_0_000773590698 = OpConstant %float 0.000773590698 +%float_n0_00134037994 = OpConstant %float -0.00134037994 +%float_0_000268075994 = OpConstant %float 0.000268075994 +%float_n0_00147824758 = OpConstant %float -0.00147824758 +%float_n0_00013020834 = OpConstant %float -0.00013020834 +%float_n0_000773590698 = OpConstant %float -0.000773590698 +%float_0_00130974269 = OpConstant %float 0.00130974269 +%float_0_000390625006 = OpConstant %float 0.000390625006 +%float_0_000957414217 = OpConstant %float 0.000957414217 +%float_n0_000467218139 = OpConstant %float -0.000467218139 +%float_n0_00153952208 = OpConstant %float -0.00153952208 +%float_0_00103400741 = OpConstant %float 0.00103400741 +%float_n0_000681678939 = OpConstant %float -0.000681678939 +%float_0_00167738972 = OpConstant %float 0.00167738972 +%float_0_00100337015 = OpConstant %float 0.00100337015 +%float_n0_000421262259 = OpConstant %float -0.000421262259 +%float_0_00178462011 = OpConstant %float 0.00178462011 +%float_n0_000237438726 = OpConstant %float -0.000237438726 +%float_n0_000620404433 = OpConstant %float -0.000620404433 +%float_0_0016620711 = OpConstant %float 0.0016620711 +%float_0_000834865205 = OpConstant %float 0.000834865205 +%float_n0_0017233456 = OpConstant %float -0.0017233456 +%float_n0_00107996329 = OpConstant %float -0.00107996329 +%float_0_00176930148 = OpConstant %float 0.00176930148 +%float_n0_000788909325 = OpConstant %float -0.000788909325 +%float_n0_00178462011 = OpConstant %float -0.00178462011 +%float_0_000681678939 = OpConstant %float 0.000681678939 +%float_n0_000988051528 = OpConstant %float -0.000988051528 +%float_n0_00132506131 = OpConstant %float -0.00132506131 +%float_n0_00017616422 = OpConstant %float -0.00017616422 +%float_n0_00150888483 = OpConstant %float -0.00150888483 +%float_0_0003293505 = OpConstant %float 0.0003293505 +%float_n0_001953125 = OpConstant %float -0.001953125 +%float_0_000666360313 = OpConstant %float 0.000666360313 +%float_n0_00161611522 = OpConstant %float -0.00161611522 +%float_0_00115655642 = OpConstant %float 0.00115655642 +%float_0_000451899512 = OpConstant %float 0.000451899512 +%float_n0_000436580885 = OpConstant %float -0.000436580885 +%float_0_000191482846 = OpConstant %float 0.000191482846 +%float_n0_0014935662 = OpConstant %float -0.0014935662 +%float_0_00114123779 = OpConstant %float 0.00114123779 +%float_8_42524532en05 = OpConstant %float 8.42524532e-05 +%float_0_00189185049 = OpConstant %float 0.00189185049 +%float_0_00140165444 = OpConstant %float 0.00140165444 +%float_0_000559129927 = OpConstant %float 0.000559129927 +%float_0_000114889706 = OpConstant %float 0.000114889706 +%float_0_00126378681 = OpConstant %float 0.00126378681 +%float_n0_000574448553 = OpConstant %float -0.000574448553 +%float_n0_000972732843 = OpConstant %float -0.000972732843 +%float_0_00132506131 = OpConstant %float 0.00132506131 +%float_0_000222120099 = OpConstant %float 0.000222120099 +%float_n0_000758272072 = OpConstant %float -0.000758272072 +%float_n0_00135569857 = OpConstant %float -0.00135569857 +%float_0_00146292895 = OpConstant %float 0.00146292895 +%float_0_000865502458 = OpConstant %float 0.000865502458 +%float_n0_000359987753 = OpConstant %float -0.000359987753 +%float_0_0005438113 = OpConstant %float 0.0005438113 +%float_n0_00112591917 = OpConstant %float -0.00112591917 +%float_n0_000252757367 = OpConstant %float -0.000252757367 +%float_n0_000559129927 = OpConstant %float -0.000559129927 +%float_n0_00181525736 = OpConstant %float -0.00181525736 +%float_0_0017233456 = OpConstant %float 0.0017233456 +%float_n0_00115655642 = OpConstant %float -0.00115655642 +%float_0_000742953445 = OpConstant %float 0.000742953445 +%float_0_00157015934 = OpConstant %float 0.00157015934 +%float_n0_000114889706 = OpConstant %float -0.000114889706 +%float_n0_00121783093 = OpConstant %float -0.00121783093 +%float_0_00183057599 = OpConstant %float 0.00183057599 +%float_2_29779416en05 = OpConstant %float 2.29779416e-05 +%float_n0_00192248775 = OpConstant %float -0.00192248775 +%float_0_00173866423 = OpConstant %float 0.00173866423 +%float_n0_000712316192 = OpConstant %float -0.000712316192 +%float_0_00155484071 = OpConstant %float 0.00155484071 +%float_n0_00170802698 = OpConstant %float -0.00170802698 +%float_0_00123314955 = OpConstant %float 0.00123314955 +%float_0_000206801473 = OpConstant %float 0.000206801473 +%float_0_00104932603 = OpConstant %float 0.00104932603 +%float_n0_000727634819 = OpConstant %float -0.000727634819 +%float_n0_00163143384 = OpConstant %float -0.00163143384 +%float_n0_000314031873 = OpConstant %float -0.000314031873 +%float_0_000482536765 = OpConstant %float 0.000482536765 +%float_n0_00179993873 = OpConstant %float -0.00179993873 +%float_0_00094209559 = OpConstant %float 0.00094209559 +%float_n0_000344669126 = OpConstant %float -0.000344669126 +%float_0_000696997566 = OpConstant %float 0.000696997566 +%float_n0_00101868878 = OpConstant %float -0.00101868878 +%float_n0_00157015934 = OpConstant %float -0.00157015934 +%float_n2_29779416en05 = OpConstant %float -2.29779416e-05 +%float_n0_00127910543 = OpConstant %float -0.00127910543 +%float_0_000804227951 = OpConstant %float 0.000804227951 +%float_n0_000896139711 = OpConstant %float -0.000896139711 +%float_n0_0014322917 = OpConstant %float -0.0014322917 +%float_0_000605085806 = OpConstant %float 0.000605085806 +%float_n8_42524532en05 = OpConstant %float -8.42524532e-05 +%float_0_000911458337 = OpConstant %float 0.000911458337 +%float_0_001953125 = OpConstant %float 0.001953125 +%float_n0_00140165444 = OpConstant %float -0.00140165444 +%float_n0_00063572306 = OpConstant %float -0.00063572306 +%float_0_00150888483 = OpConstant %float 0.00150888483 +%float_n0_000819546578 = OpConstant %float -0.000819546578 +%float_0_00124846818 = OpConstant %float 0.00124846818 +%float_0_000252757367 = OpConstant %float 0.000252757367 +%float_0_00152420346 = OpConstant %float 0.00152420346 +%float_0_00112591917 = OpConstant %float 0.00112591917 +%float_0_000359987753 = OpConstant %float 0.000359987753 +%float_n0_000390625006 = OpConstant %float -0.000390625006 +%float_0_00190716912 = OpConstant %float 0.00190716912 +%float_0_00138633582 = OpConstant %float 0.00138633582 +%float_n0_00111060054 = OpConstant %float -0.00111060054 +%float_0_00161611522 = OpConstant %float 0.00161611522 +%float_n0_000880821084 = OpConstant %float -0.000880821084 +%float_0_000145526967 = OpConstant %float 0.000145526967 +%float_0_00107996329 = OpConstant %float 0.00107996329 +%float_n5_36151965en05 = OpConstant %float -5.36151965e-05 +%float_0_00028339462 = OpConstant %float 0.00028339462 +%float_n0_00169270835 = OpConstant %float -0.00169270835 +%float_n0_00126378681 = OpConstant %float -0.00126378681 +%float_n0_000513174047 = OpConstant %float -0.000513174047 +%float_n0_000160845593 = OpConstant %float -0.000160845593 +%float_n0_00187653187 = OpConstant %float -0.00187653187 +%float_n0_000834865205 = OpConstant %float -0.000834865205 +%float_0_00063572306 = OpConstant %float 0.00063572306 +%float_7_65931418en06 = OpConstant %float 7.65931418e-06 +%float_n0_00190716912 = OpConstant %float -0.00190716912 +%float_n0_000222120099 = OpConstant %float -0.000222120099 +%float_0_000375306379 = OpConstant %float 0.000375306379 +%float_n0_00173866423 = OpConstant %float -0.00173866423 +%float_n0_000405943632 = OpConstant %float -0.000405943632 +%float_n0_00123314955 = OpConstant %float -0.00123314955 +%float_0_00170802698 = OpConstant %float 0.00170802698 +%float_n0_00094209559 = OpConstant %float -0.00094209559 +%float_0_000819546578 = OpConstant %float 0.000819546578 +%float_0_00184589461 = OpConstant %float 0.00184589461 +%float_0_000467218139 = OpConstant %float 0.000467218139 + %337 = OpConstantComposite %_arr_float_uint_256 %float_n0_00100337015 %float_0_000880821084 %float_0_00169270835 %float_n0_00155484071 %float_0_00127910543 %float_n0_000605085806 %float_0_00106464466 %float_n0_00138633582 %float_0_00135569857 %float_0_000513174047 %float_0_00121783093 %float_n0_00160079659 %float_0_00058976718 %float_n0_00028339462 %float_0_00111060054 %float_n0_00141697307 %float_0_00144761032 %float_n0_0005438113 %float_0_00013020834 %float_n0_0012025123 %float_0_000436580885 %float_n0_00104932603 %float_0_000620404433 %float_n0_000482536765 %float_0_00187653187 %float_n0_00109528191 %float_n9_95710798en05 %float_n0_000528492674 %float_0_0014322917 %float_n0_00193780637 %float_n0_000696997566 %float_3_829657en05 %float_0_000712316192 %float_n0_00130974269 %float_0_00109528191 %float_n0_000298713247 %float_0_00175398286 %float_n0_00167738972 %float_0_00147824758 %float_n3_829657en05 %float_0_000788909325 %float_n0_00183057599 %float_0_000298713247 %float_0_000988051528 %float_n0_00117187505 %float_0_00017616422 %float_0_00164675247 %float_n0_00158547796 %float_0_000344669126 %float_0_00186121324 %float_n0_00176930148 %float_n0_000865502458 %float_0_000896139711 %float_0_000160845593 %float_n0_000926776964 %float_n0_00152420346 %float_n0_000651041686 %float_0_00129442406 %float_n0_000804227951 %float_n0_00146292895 %float_0_00179993873 %float_n0_000850183831 %float_0_000850183831 %float_n0_000451899512 %float_n0_00106464466 %float_n0_000145526967 %float_0_000237438726 %float_0_00141697307 %float_n0_00058976718 %float_n0_000191482846 %float_0_00160079659 %float_0_00101868878 %float_0_000405943632 %float_n0_000206801473 %float_0_00158547796 %float_0_000651041686 %float_n6_89338267en05 %float_0_000421262259 %float_n0_00164675247 %float_0_00137101719 %float_0_000926776964 %float_n0_000666360313 %float_0_00118719367 %float_n0_00144761032 %float_0_000574448553 %float_n0_00189185049 %float_0_000758272072 %float_n0_00129442406 %float_0_00192248775 %float_n0_0016620711 %float_n0_00103400741 %float_n0_000497855421 %float_n0_00186121324 %float_0_0012025123 %float_n0_0003293505 %float_n0_00137101719 %float_0_00163143384 %float_n0_00184589461 %float_0_000727634819 %float_n0_000911458337 %float_0_00181525736 %float_n0_00114123779 %float_n0_000375306379 %float_9_95710798en05 %float_n0_000742953445 %float_0_00117187505 %float_6_89338267en05 %float_0_0014935662 %float_0_000972732843 %float_n0_000957414217 %float_0_00193780637 %float_0_000528492674 %float_5_36151965en05 %float_n0_00124846818 %float_n0_000268075994 %float_0_00153952208 %float_n7_65931418en06 %float_0_000314031873 %float_0_00134037994 %float_n0_00175398286 %float_0_000497855421 %float_n0_00118719367 %float_0_000773590698 %float_n0_00134037994 %float_0_000268075994 %float_n0_00147824758 %float_n0_00013020834 %float_n0_000773590698 %float_0_00130974269 %float_0_000390625006 %float_0_000957414217 %float_n0_000467218139 %float_n0_00153952208 %float_0_00103400741 %float_n0_000681678939 %float_0_00167738972 %float_0_00100337015 %float_n0_000421262259 %float_0_00178462011 %float_n0_000237438726 %float_n0_000620404433 %float_0_0016620711 %float_0_000834865205 %float_n0_0017233456 %float_n0_00107996329 %float_0_00176930148 %float_n0_000788909325 %float_n0_00178462011 %float_0_000681678939 %float_n0_000988051528 %float_n0_00132506131 %float_n0_00017616422 %float_n0_00150888483 %float_0_0003293505 %float_n0_001953125 %float_0_000666360313 %float_n0_00161611522 %float_0_00115655642 %float_0_000451899512 %float_n0_000436580885 %float_0_000191482846 %float_n0_0014935662 %float_0_00114123779 %float_8_42524532en05 %float_0_00189185049 %float_0_00140165444 %float_0_000559129927 %float_0_000114889706 %float_0_00126378681 %float_n0_000574448553 %float_n0_000972732843 %float_0_00132506131 %float_0_000222120099 %float_n0_000758272072 %float_n0_00135569857 %float_0_00146292895 %float_0_000865502458 %float_n0_000359987753 %float_0_0005438113 %float_n0_00112591917 %float_n0_000252757367 %float_n0_000559129927 %float_n0_00181525736 %float_0_0017233456 %float_n0_00115655642 %float_0_000742953445 %float_0_00157015934 %float_n0_000114889706 %float_n0_00121783093 %float_0_00183057599 %float_2_29779416en05 %float_n0_00192248775 %float_0_00173866423 %float_n0_000712316192 %float_0_00155484071 %float_n0_00170802698 %float_0_00123314955 %float_0_000206801473 %float_0_00104932603 %float_n0_000727634819 %float_n0_00163143384 %float_n0_000314031873 %float_0_000482536765 %float_n0_00179993873 %float_0_00094209559 %float_n0_000344669126 %float_0_000696997566 %float_n0_00101868878 %float_n0_00157015934 %float_n2_29779416en05 %float_n0_00127910543 %float_0_000804227951 %float_n0_000896139711 %float_n0_0014322917 %float_0_000605085806 %float_n8_42524532en05 %float_0_000911458337 %float_0_001953125 %float_n0_00140165444 %float_n0_00063572306 %float_0_00150888483 %float_n0_000819546578 %float_0_00124846818 %float_0_000252757367 %float_0_00152420346 %float_0_00112591917 %float_0_000359987753 %float_n0_000390625006 %float_0_00190716912 %float_0_00138633582 %float_n0_00111060054 %float_0_00161611522 %float_n0_000880821084 %float_0_000145526967 %float_0_00107996329 %float_n5_36151965en05 %float_0_00028339462 %float_n0_00169270835 %float_n0_00126378681 %float_n0_000513174047 %float_n0_000160845593 %float_n0_00187653187 %float_n0_000834865205 %float_0_00063572306 %float_7_65931418en06 %float_n0_00190716912 %float_n0_000222120099 %float_0_000375306379 %float_n0_00173866423 %float_n0_000405943632 %float_n0_00123314955 %float_0_00170802698 %float_n0_00094209559 %float_0_000819546578 %float_0_00184589461 %float_0_000467218139 + %uint_1 = OpConstant %uint 1 + %uint_16 = OpConstant %uint 16 + %uint_0 = OpConstant %uint 0 +%_ptr_Function__arr_float_uint_256 = OpTypePointer Function %_arr_float_uint_256 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 +%uint_532432441 = OpConstant %uint 532432441 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %424 = OpTypeImage %float 2D 0 0 0 1 Unknown + %425 = OpTypeSampledImage %424 +%_ptr_UniformConstant_425 = OpTypePointer UniformConstant %425 + %xe_texture = OpVariable %_ptr_UniformConstant_425 UniformConstant + %int_0 = OpConstant %int 0 + %v4float = OpTypeVector %float 4 + %int_n1 = OpConstant %int -1 + %462 = OpConstantComposite %v2int %int_0 %int_n1 + %int_1 = OpConstant %int 1 + %469 = OpConstantComposite %v2int %int_1 %int_n1 + %475 = OpConstantComposite %v2int %int_n1 %int_0 + %485 = OpConstantComposite %v2int %int_1 %int_0 + %491 = OpConstantComposite %v2int %int_n1 %int_1 + %497 = OpConstantComposite %v2int %int_0 %int_1 + %503 = OpConstantComposite %v2int %int_1 %int_1 + %uint_2 = OpConstant %uint 2 + %v2float = OpTypeVector %float 2 + %int_2 = OpConstant %int 2 + %992 = OpConstantComposite %v2int %int_2 %int_0 + %1014 = OpConstantComposite %v2int %int_0 %int_2 + %1025 = OpConstantComposite %v2int %int_2 %int_1 + %1031 = OpConstantComposite %v2int %int_1 %int_2 +%float_0_03125 = OpConstant %float 0.03125 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeCasResampleConstants = OpTypeStruct %v2int %v2float %float +%_ptr_PushConstant_XeCasResampleConstants = OpTypePointer PushConstant %XeCasResampleConstants + %_ = OpVariable %_ptr_PushConstant_XeCasResampleConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %float_0_5 = OpConstant %float 0.5 +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %2565 = OpConstantComposite %v3float %float_0 %float_0 %float_0 + %2566 = OpConstantComposite %v3float %float_1 %float_1 %float_1 + %uint_3 = OpConstant %uint 3 + %6773 = OpConstantComposite %v2float %float_0_5 %float_0_5 + %6789 = OpConstantComposite %v2uint %uint_15 %uint_15 + %main = OpFunction %void None %3 + %5 = OpLabel + %6321 = OpVariable %_ptr_Function__arr_float_uint_256 Function + %2485 = OpLoad %v4float %gl_FragCoord + %2486 = OpVectorShuffle %v2float %2485 %2485 0 1 + %2487 = OpConvertFToS %v2int %2486 + %2492 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %2493 = OpLoad %v2int %2492 + %2494 = OpISub %v2int %2487 %2493 + %2495 = OpBitcast %v2uint %2494 + %2498 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_1 + %2499 = OpLoad %v2float %2498 + %2500 = OpBitcast %v2uint %2499 + %2504 = OpVectorTimesScalar %v2float %2499 %float_0_5 + %2506 = OpFSub %v2float %2504 %6773 + %2507 = OpBitcast %v2uint %2506 + %2515 = OpAccessChain %_ptr_PushConstant_float %_ %int_2 + %2516 = OpLoad %float %2515 + %2517 = OpBitcast %uint %2516 + OpBranch %3081 + %3081 = OpLabel + %3432 = OpConvertUToF %v2float %2495 + %3438 = OpBitcast %v2float %2500 + %3439 = OpFMul %v2float %3432 %3438 + %3445 = OpBitcast %v2float %2507 + %3446 = OpFAdd %v2float %3439 %3445 + %3448 = OpExtInst %v2float %1 Floor %3446 + %3451 = OpFSub %v2float %3446 %3448 + %3453 = OpConvertFToS %v2int %3448 + %3458 = OpIAdd %v2int %3453 %462 + %5048 = OpLoad %425 %xe_texture + %5050 = OpImage %424 %5048 + %5051 = OpImageFetch %v4float %5050 %3458 Lod %int_0 + %3461 = OpIAdd %v2int %3453 %475 + %5057 = OpImage %424 %5048 + %5058 = OpImageFetch %v4float %5057 %3461 Lod %int_0 + %5064 = OpImage %424 %5048 + %5065 = OpImageFetch %v4float %5064 %3453 Lod %int_0 + %3466 = OpIAdd %v2int %3453 %469 + %5071 = OpImage %424 %5048 + %5072 = OpImageFetch %v4float %5071 %3466 Lod %int_0 + %3472 = OpIAdd %v2int %3453 %485 + %5085 = OpImage %424 %5048 + %5086 = OpImageFetch %v4float %5085 %3472 Lod %int_0 + %3475 = OpIAdd %v2int %3453 %992 + %5092 = OpImage %424 %5048 + %5093 = OpImageFetch %v4float %5092 %3475 Lod %int_0 + %3478 = OpIAdd %v2int %3453 %491 + %5099 = OpImage %424 %5048 + %5100 = OpImageFetch %v4float %5099 %3478 Lod %int_0 + %3481 = OpIAdd %v2int %3453 %497 + %5106 = OpImage %424 %5048 + %5107 = OpImageFetch %v4float %5106 %3481 Lod %int_0 + %3487 = OpIAdd %v2int %3453 %1014 + %5120 = OpImage %424 %5048 + %5121 = OpImageFetch %v4float %5120 %3487 Lod %int_0 + %3490 = OpIAdd %v2int %3453 %503 + %5127 = OpImage %424 %5048 + %5128 = OpImageFetch %v4float %5127 %3490 Lod %int_0 + %3493 = OpIAdd %v2int %3453 %1025 + %5134 = OpImage %424 %5048 + %5135 = OpImageFetch %v4float %5134 %3493 Lod %int_0 + %3496 = OpIAdd %v2int %3453 %1031 + %5141 = OpImage %424 %5048 + %5142 = OpImageFetch %v4float %5141 %3496 Lod %int_0 + %3515 = OpCompositeExtract %float %5051 0 + %3517 = OpCompositeExtract %float %5051 1 + %3519 = OpCompositeExtract %float %5051 2 + %5164 = OpFMul %float %3515 %3515 + %5167 = OpFMul %float %3517 %3517 + %5170 = OpFMul %float %3519 %3519 + %3528 = OpCompositeExtract %float %5072 0 + %3530 = OpCompositeExtract %float %5072 1 + %3532 = OpCompositeExtract %float %5072 2 + %5174 = OpFMul %float %3528 %3528 + %5177 = OpFMul %float %3530 %3530 + %5180 = OpFMul %float %3532 %3532 + %3554 = OpCompositeExtract %float %5058 0 + %3556 = OpCompositeExtract %float %5058 1 + %3558 = OpCompositeExtract %float %5058 2 + %5194 = OpFMul %float %3554 %3554 + %5197 = OpFMul %float %3556 %3556 + %5200 = OpFMul %float %3558 %3558 + %3567 = OpCompositeExtract %float %5065 0 + %3569 = OpCompositeExtract %float %5065 1 + %3571 = OpCompositeExtract %float %5065 2 + %5204 = OpFMul %float %3567 %3567 + %5207 = OpFMul %float %3569 %3569 + %5210 = OpFMul %float %3571 %3571 + %3580 = OpCompositeExtract %float %5086 0 + %3582 = OpCompositeExtract %float %5086 1 + %3584 = OpCompositeExtract %float %5086 2 + %5214 = OpFMul %float %3580 %3580 + %5217 = OpFMul %float %3582 %3582 + %5220 = OpFMul %float %3584 %3584 + %3593 = OpCompositeExtract %float %5093 0 + %3595 = OpCompositeExtract %float %5093 1 + %3597 = OpCompositeExtract %float %5093 2 + %5224 = OpFMul %float %3593 %3593 + %5227 = OpFMul %float %3595 %3595 + %5230 = OpFMul %float %3597 %3597 + %3606 = OpCompositeExtract %float %5100 0 + %3608 = OpCompositeExtract %float %5100 1 + %3610 = OpCompositeExtract %float %5100 2 + %5234 = OpFMul %float %3606 %3606 + %5237 = OpFMul %float %3608 %3608 + %5240 = OpFMul %float %3610 %3610 + %3619 = OpCompositeExtract %float %5107 0 + %3621 = OpCompositeExtract %float %5107 1 + %3623 = OpCompositeExtract %float %5107 2 + %5244 = OpFMul %float %3619 %3619 + %5247 = OpFMul %float %3621 %3621 + %5250 = OpFMul %float %3623 %3623 + %3632 = OpCompositeExtract %float %5128 0 + %3634 = OpCompositeExtract %float %5128 1 + %3636 = OpCompositeExtract %float %5128 2 + %5254 = OpFMul %float %3632 %3632 + %5257 = OpFMul %float %3634 %3634 + %5260 = OpFMul %float %3636 %3636 + %3645 = OpCompositeExtract %float %5135 0 + %3647 = OpCompositeExtract %float %5135 1 + %3649 = OpCompositeExtract %float %5135 2 + %5264 = OpFMul %float %3645 %3645 + %5267 = OpFMul %float %3647 %3647 + %5270 = OpFMul %float %3649 %3649 + %3671 = OpCompositeExtract %float %5121 0 + %3673 = OpCompositeExtract %float %5121 1 + %3675 = OpCompositeExtract %float %5121 2 + %5284 = OpFMul %float %3671 %3671 + %5287 = OpFMul %float %3673 %3673 + %5290 = OpFMul %float %3675 %3675 + %3684 = OpCompositeExtract %float %5142 0 + %3686 = OpCompositeExtract %float %5142 1 + %3688 = OpCompositeExtract %float %5142 2 + %5294 = OpFMul %float %3684 %3684 + %5297 = OpFMul %float %3686 %3686 + %5300 = OpFMul %float %3688 %3688 + %5330 = OpExtInst %float %1 FMin %5197 %5207 + %5331 = OpExtInst %float %1 FMin %5167 %5330 + %5337 = OpExtInst %float %1 FMin %5217 %5247 + %5338 = OpExtInst %float %1 FMin %5331 %5337 + %5372 = OpExtInst %float %1 FMax %5197 %5207 + %5373 = OpExtInst %float %1 FMax %5167 %5372 + %5379 = OpExtInst %float %1 FMax %5217 %5247 + %5380 = OpExtInst %float %1 FMax %5373 %5379 + %5414 = OpExtInst %float %1 FMin %5207 %5217 + %5415 = OpExtInst %float %1 FMin %5177 %5414 + %5421 = OpExtInst %float %1 FMin %5227 %5257 + %5422 = OpExtInst %float %1 FMin %5415 %5421 + %5456 = OpExtInst %float %1 FMax %5207 %5217 + %5457 = OpExtInst %float %1 FMax %5177 %5456 + %5463 = OpExtInst %float %1 FMax %5227 %5257 + %5464 = OpExtInst %float %1 FMax %5457 %5463 + %5498 = OpExtInst %float %1 FMin %5237 %5247 + %5499 = OpExtInst %float %1 FMin %5207 %5498 + %5505 = OpExtInst %float %1 FMin %5257 %5287 + %5506 = OpExtInst %float %1 FMin %5499 %5505 + %5540 = OpExtInst %float %1 FMax %5237 %5247 + %5541 = OpExtInst %float %1 FMax %5207 %5540 + %5547 = OpExtInst %float %1 FMax %5257 %5287 + %5548 = OpExtInst %float %1 FMax %5541 %5547 + %5582 = OpExtInst %float %1 FMin %5247 %5257 + %5583 = OpExtInst %float %1 FMin %5217 %5582 + %5589 = OpExtInst %float %1 FMin %5267 %5297 + %5590 = OpExtInst %float %1 FMin %5583 %5589 + %5624 = OpExtInst %float %1 FMax %5247 %5257 + %5625 = OpExtInst %float %1 FMax %5217 %5624 + %5631 = OpExtInst %float %1 FMax %5267 %5297 + %5632 = OpExtInst %float %1 FMax %5625 %5631 + %5663 = OpBitcast %uint %5380 + %5664 = OpISub %uint %uint_2129690299 %5663 + %5665 = OpBitcast %float %5664 + %5696 = OpBitcast %uint %5464 + %5697 = OpISub %uint %uint_2129690299 %5696 + %5698 = OpBitcast %float %5697 + %5729 = OpBitcast %uint %5548 + %5730 = OpISub %uint %uint_2129690299 %5729 + %5731 = OpBitcast %float %5730 + %5762 = OpBitcast %uint %5632 + %5763 = OpISub %uint %uint_2129690299 %5762 + %5764 = OpBitcast %float %5763 + %4032 = OpFSub %float %float_1 %5380 + %4033 = OpExtInst %float %1 FMin %5338 %4032 + %4035 = OpFMul %float %4033 %5665 + %5806 = OpExtInst %float %1 FClamp %4035 %float_0 %float_1 + %4056 = OpFSub %float %float_1 %5464 + %4057 = OpExtInst %float %1 FMin %5422 %4056 + %4059 = OpFMul %float %4057 %5698 + %5857 = OpExtInst %float %1 FClamp %4059 %float_0 %float_1 + %4080 = OpFSub %float %float_1 %5548 + %4081 = OpExtInst %float %1 FMin %5506 %4080 + %4083 = OpFMul %float %4081 %5731 + %5908 = OpExtInst %float %1 FClamp %4083 %float_0 %float_1 + %4104 = OpFSub %float %float_1 %5632 + %4105 = OpExtInst %float %1 FMin %5590 %4104 + %4107 = OpFMul %float %4105 %5764 + %5959 = OpExtInst %float %1 FClamp %4107 %float_0 %float_1 + %6005 = OpBitcast %uint %5806 + %6007 = OpShiftRightLogical %uint %6005 %uint_1 + %6009 = OpIAdd %uint %6007 %uint_532432441 + %6010 = OpBitcast %float %6009 + %6056 = OpBitcast %uint %5857 + %6058 = OpShiftRightLogical %uint %6056 %uint_1 + %6060 = OpIAdd %uint %6058 %uint_532432441 + %6061 = OpBitcast %float %6060 + %6107 = OpBitcast %uint %5908 + %6109 = OpShiftRightLogical %uint %6107 %uint_1 + %6111 = OpIAdd %uint %6109 %uint_532432441 + %6112 = OpBitcast %float %6111 + %6158 = OpBitcast %uint %5959 + %6160 = OpShiftRightLogical %uint %6158 %uint_1 + %6162 = OpIAdd %uint %6160 %uint_532432441 + %6163 = OpBitcast %float %6162 + %4143 = OpBitcast %float %2517 + %4149 = OpFMul %float %6010 %4143 + %4158 = OpFMul %float %6061 %4143 + %4167 = OpFMul %float %6112 %4143 + %4176 = OpFMul %float %6163 %4143 + %4182 = OpCompositeExtract %float %3451 0 + %4183 = OpFSub %float %float_1 %4182 + %4186 = OpCompositeExtract %float %3451 1 + %4187 = OpFSub %float %float_1 %4186 + %4188 = OpFMul %float %4183 %4187 + %4195 = OpFMul %float %4182 %4187 + %4202 = OpFMul %float %4183 %4186 + %4207 = OpFMul %float %4182 %4186 + %4211 = OpFSub %float %5380 %5338 + %4212 = OpFAdd %float %float_0_03125 %4211 + %6204 = OpBitcast %uint %4212 + %6205 = OpISub %uint %uint_2129690299 %6204 + %6206 = OpBitcast %float %6205 + %4215 = OpFMul %float %4188 %6206 + %4219 = OpFSub %float %5464 %5422 + %4220 = OpFAdd %float %float_0_03125 %4219 + %6215 = OpBitcast %uint %4220 + %6216 = OpISub %uint %uint_2129690299 %6215 + %6217 = OpBitcast %float %6216 + %4223 = OpFMul %float %4195 %6217 + %4227 = OpFSub %float %5548 %5506 + %4228 = OpFAdd %float %float_0_03125 %4227 + %6226 = OpBitcast %uint %4228 + %6227 = OpISub %uint %uint_2129690299 %6226 + %6228 = OpBitcast %float %6227 + %4231 = OpFMul %float %4202 %6228 + %4235 = OpFSub %float %5632 %5590 + %4236 = OpFAdd %float %float_0_03125 %4235 + %6237 = OpBitcast %uint %4236 + %6238 = OpISub %uint %uint_2129690299 %6237 + %6239 = OpBitcast %float %6238 + %4239 = OpFMul %float %4207 %6239 + %4245 = OpFMul %float %4149 %4215 + %4254 = OpFMul %float %4158 %4223 + %4272 = OpFMul %float %4167 %4231 + %4273 = OpFAdd %float %4254 %4272 + %4275 = OpFAdd %float %4273 %4215 + %4299 = OpFMul %float %4176 %4239 + %4300 = OpFAdd %float %4245 %4299 + %4302 = OpFAdd %float %4300 %4223 + %4329 = OpFAdd %float %4300 %4231 + %4356 = OpFAdd %float %4273 %4239 + %6774 = OpFAdd %float %4245 %4254 + %6775 = OpFAdd %float %6774 %4272 + %6776 = OpFAdd %float %6775 %4299 + %4398 = OpFMul %float %float_2 %6776 + %4400 = OpFAdd %float %4398 %4275 + %4402 = OpFAdd %float %4400 %4302 + %4404 = OpFAdd %float %4402 %4329 + %4406 = OpFAdd %float %4404 %4356 + %6262 = OpBitcast %uint %4406 + %6263 = OpISub %uint %uint_2129764351 %6262 + %6264 = OpBitcast %float %6263 + %6267 = OpFNegate %float %6264 + %6269 = OpFMul %float %6267 %4406 + %6271 = OpFAdd %float %6269 %float_2 + %6272 = OpFMul %float %6264 %6271 + %6777 = OpFAdd %float %5164 %5194 + %4416 = OpFMul %float %4245 %6777 + %4420 = OpFMul %float %5174 %4254 + %4421 = OpFAdd %float %4416 %4420 + %4425 = OpFMul %float %5224 %4254 + %4426 = OpFAdd %float %4421 %4425 + %4430 = OpFMul %float %5234 %4272 + %4431 = OpFAdd %float %4426 %4430 + %4435 = OpFMul %float %5284 %4272 + %4436 = OpFAdd %float %4431 %4435 + %4440 = OpFMul %float %5264 %4299 + %4441 = OpFAdd %float %4436 %4440 + %4445 = OpFMul %float %5294 %4299 + %4446 = OpFAdd %float %4441 %4445 + %4450 = OpFMul %float %5204 %4275 + %4451 = OpFAdd %float %4446 %4450 + %4455 = OpFMul %float %5214 %4302 + %4456 = OpFAdd %float %4451 %4455 + %4460 = OpFMul %float %5244 %4329 + %4461 = OpFAdd %float %4456 %4460 + %4465 = OpFMul %float %5254 %4356 + %4466 = OpFAdd %float %4461 %4465 + %4468 = OpFMul %float %4466 %6272 + %6286 = OpExtInst %float %1 FClamp %4468 %float_0 %float_1 + %6778 = OpFAdd %float %5167 %5197 + %4478 = OpFMul %float %4245 %6778 + %4482 = OpFMul %float %5177 %4254 + %4483 = OpFAdd %float %4478 %4482 + %4487 = OpFMul %float %5227 %4254 + %4488 = OpFAdd %float %4483 %4487 + %4492 = OpFMul %float %5237 %4272 + %4493 = OpFAdd %float %4488 %4492 + %4497 = OpFMul %float %5287 %4272 + %4498 = OpFAdd %float %4493 %4497 + %4502 = OpFMul %float %5267 %4299 + %4503 = OpFAdd %float %4498 %4502 + %4507 = OpFMul %float %5297 %4299 + %4508 = OpFAdd %float %4503 %4507 + %4512 = OpFMul %float %5207 %4275 + %4513 = OpFAdd %float %4508 %4512 + %4517 = OpFMul %float %5217 %4302 + %4518 = OpFAdd %float %4513 %4517 + %4522 = OpFMul %float %5247 %4329 + %4523 = OpFAdd %float %4518 %4522 + %4527 = OpFMul %float %5257 %4356 + %4528 = OpFAdd %float %4523 %4527 + %4530 = OpFMul %float %4528 %6272 + %6300 = OpExtInst %float %1 FClamp %4530 %float_0 %float_1 + %6779 = OpFAdd %float %5170 %5200 + %4540 = OpFMul %float %4245 %6779 + %4544 = OpFMul %float %5180 %4254 + %4545 = OpFAdd %float %4540 %4544 + %4549 = OpFMul %float %5230 %4254 + %4550 = OpFAdd %float %4545 %4549 + %4554 = OpFMul %float %5240 %4272 + %4555 = OpFAdd %float %4550 %4554 + %4559 = OpFMul %float %5290 %4272 + %4560 = OpFAdd %float %4555 %4559 + %4564 = OpFMul %float %5270 %4299 + %4565 = OpFAdd %float %4560 %4564 + %4569 = OpFMul %float %5300 %4299 + %4570 = OpFAdd %float %4565 %4569 + %4574 = OpFMul %float %5210 %4275 + %4575 = OpFAdd %float %4570 %4574 + %4579 = OpFMul %float %5220 %4302 + %4580 = OpFAdd %float %4575 %4579 + %4584 = OpFMul %float %5250 %4329 + %4585 = OpFAdd %float %4580 %4584 + %4589 = OpFMul %float %5260 %4356 + %4590 = OpFAdd %float %4585 %4589 + %4592 = OpFMul %float %4590 %6272 + %6314 = OpExtInst %float %1 FClamp %4592 %float_0 %float_1 + %2544 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %2544 %6286 + %2546 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %2546 %6300 + %2548 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %2548 %6314 + %2549 = OpLoad %v4float %xe_frag_color + %2550 = OpVectorShuffle %v3float %2549 %2549 0 1 2 + %2551 = OpExtInst %v3float %1 Sqrt %2550 + %2553 = OpCompositeExtract %float %2551 0 + OpStore %2544 %2553 + %2555 = OpCompositeExtract %float %2551 1 + OpStore %2546 %2555 + %2557 = OpCompositeExtract %float %2551 2 + OpStore %2548 %2557 + %2558 = OpLoad %v4float %xe_frag_color + %2559 = OpVectorShuffle %v3float %2558 %2558 0 1 2 + %6326 = OpBitwiseAnd %v2uint %2495 %6789 + %6328 = OpCompositeExtract %uint %6326 1 + %6329 = OpIMul %uint %6328 %uint_16 + %6331 = OpCompositeExtract %uint %6326 0 + %6332 = OpIAdd %uint %6329 %6331 + OpStore %6321 %337 + %6333 = OpAccessChain %_ptr_Function_float %6321 %6332 + %6334 = OpLoad %float %6333 + %2563 = OpCompositeConstruct %v3float %6334 %6334 %6334 + %2564 = OpFAdd %v3float %2559 %2563 + %2567 = OpExtInst %v3float %1 FClamp %2564 %2565 %2566 + %2569 = OpCompositeExtract %float %2567 0 + OpStore %2544 %2569 + %2571 = OpCompositeExtract %float %2567 1 + OpStore %2546 %2571 + %2573 = OpCompositeExtract %float %2567 2 + OpStore %2548 %2573 + %2575 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %2575 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h new file mode 100644 index 000000000..09eb0c3dc --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h @@ -0,0 +1,748 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_cas_resample.frag +const uint8_t guest_output_ffx_cas_resample_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x44, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x92, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x58, 0x65, 0x43, 0x61, 0x73, 0x52, 0x65, 0x73, + 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, + 0x74, 0x73, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x6F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x69, + 0x6E, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, + 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x00, 0x00, + 0x06, 0x00, 0x0A, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x70, + 0x6E, 0x65, 0x73, 0x73, 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x73, 0x65, + 0x74, 0x75, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, 0xA2, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x9C, 0x08, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, + 0x39, 0x46, 0xBC, 0x1F, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x09, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x91, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xC8, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xDE, 0x02, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xE9, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xEF, 0x02, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3D, 0x20, 0x00, 0x04, 0x00, 0x9B, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x9B, 0x08, 0x00, 0x00, 0x9C, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x05, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xA1, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xA1, 0x08, 0x00, 0x00, 0xA2, 0x08, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xA3, 0x08, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xA9, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x20, 0x00, 0x04, 0x00, 0xBA, 0x08, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xC8, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xC8, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xD7, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE6, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, 0x3D, 0x19, 0x00, 0x00, + 0xAD, 0x08, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x9E, 0x08, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x9F, 0x08, 0x00, 0x00, 0x9E, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xA3, 0x08, 0x00, 0x00, 0xA4, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xA5, 0x08, 0x00, 0x00, 0xA4, 0x08, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xA6, 0x08, 0x00, 0x00, + 0x9F, 0x08, 0x00, 0x00, 0xA5, 0x08, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x37, 0x00, 0x00, 0x00, 0xA7, 0x08, 0x00, 0x00, 0xA6, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xA9, 0x08, 0x00, 0x00, 0xAA, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0xAB, 0x08, 0x00, 0x00, 0xAA, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, 0xAC, 0x08, 0x00, 0x00, + 0xAB, 0x08, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, + 0xB0, 0x08, 0x00, 0x00, 0xAB, 0x08, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, 0xB2, 0x08, 0x00, 0x00, + 0xB0, 0x08, 0x00, 0x00, 0x3D, 0x19, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x37, 0x00, 0x00, 0x00, 0xB3, 0x08, 0x00, 0x00, 0xB2, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xBA, 0x08, 0x00, 0x00, 0xBB, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBC, 0x08, 0x00, 0x00, 0xBB, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xBD, 0x08, 0x00, 0x00, + 0xBC, 0x08, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xE1, 0x0A, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0xE1, 0x0A, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0xA7, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x86, 0x02, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, + 0xAC, 0x08, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x47, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x86, 0x02, 0x00, 0x00, 0x4D, 0x0C, 0x00, 0x00, + 0xB3, 0x08, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x4E, 0x0C, 0x00, 0x00, 0x47, 0x0C, 0x00, 0x00, 0x4D, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x86, 0x02, 0x00, 0x00, 0x50, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4E, 0x0C, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, + 0x4E, 0x0C, 0x00, 0x00, 0x50, 0x0C, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, 0x50, 0x0C, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x5A, 0x0C, 0x00, 0x00, + 0x55, 0x0C, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x92, 0x12, 0x00, 0x00, + 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x93, 0x12, 0x00, 0x00, 0x92, 0x12, 0x00, 0x00, 0x5A, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x5D, 0x0C, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x99, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x9A, 0x12, 0x00, 0x00, 0x99, 0x12, 0x00, 0x00, + 0x5D, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, + 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xA1, 0x12, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x62, 0x0C, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xA7, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xA8, 0x12, 0x00, 0x00, 0xA7, 0x12, 0x00, 0x00, + 0x62, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x68, 0x0C, 0x00, 0x00, + 0x55, 0x0C, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xB5, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xB6, 0x12, 0x00, 0x00, + 0xB5, 0x12, 0x00, 0x00, 0x68, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x6B, 0x0C, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, 0xC8, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xBC, 0x12, 0x00, 0x00, + 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xBD, 0x12, 0x00, 0x00, 0xBC, 0x12, 0x00, 0x00, 0x6B, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x6E, 0x0C, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, + 0xD2, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xC3, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xC4, 0x12, 0x00, 0x00, 0xC3, 0x12, 0x00, 0x00, + 0x6E, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x71, 0x0C, 0x00, 0x00, + 0x55, 0x0C, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xCA, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xCB, 0x12, 0x00, 0x00, + 0xCA, 0x12, 0x00, 0x00, 0x71, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x77, 0x0C, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, 0xDE, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xD8, 0x12, 0x00, 0x00, + 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xD9, 0x12, 0x00, 0x00, 0xD8, 0x12, 0x00, 0x00, 0x77, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x7A, 0x0C, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xDF, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xE0, 0x12, 0x00, 0x00, 0xDF, 0x12, 0x00, 0x00, + 0x7A, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x7D, 0x0C, 0x00, 0x00, + 0x55, 0x0C, 0x00, 0x00, 0xE9, 0x02, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xE6, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xE7, 0x12, 0x00, 0x00, + 0xE6, 0x12, 0x00, 0x00, 0x7D, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x80, 0x0C, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, 0xEF, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xED, 0x12, 0x00, 0x00, + 0x90, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xEE, 0x12, 0x00, 0x00, 0xED, 0x12, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x93, 0x0C, 0x00, 0x00, 0x93, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x95, 0x0C, 0x00, 0x00, 0x93, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x97, 0x0C, 0x00, 0x00, + 0x93, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x13, 0x00, 0x00, 0x93, 0x0C, 0x00, 0x00, + 0x93, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x13, 0x00, 0x00, 0x95, 0x0C, 0x00, 0x00, 0x95, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x13, 0x00, 0x00, + 0x97, 0x0C, 0x00, 0x00, 0x97, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, 0xA8, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA2, 0x0C, 0x00, 0x00, 0xA8, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA4, 0x0C, 0x00, 0x00, + 0xA8, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x13, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, + 0xA0, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x11, 0x13, 0x00, 0x00, 0xA2, 0x0C, 0x00, 0x00, 0xA2, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x13, 0x00, 0x00, + 0xA4, 0x0C, 0x00, 0x00, 0xA4, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBA, 0x0C, 0x00, 0x00, 0x9A, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBC, 0x0C, 0x00, 0x00, 0x9A, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBE, 0x0C, 0x00, 0x00, + 0x9A, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x22, 0x13, 0x00, 0x00, 0xBA, 0x0C, 0x00, 0x00, + 0xBA, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x25, 0x13, 0x00, 0x00, 0xBC, 0x0C, 0x00, 0x00, 0xBC, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, 0x13, 0x00, 0x00, + 0xBE, 0x0C, 0x00, 0x00, 0xBE, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC7, 0x0C, 0x00, 0x00, 0xA1, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC9, 0x0C, 0x00, 0x00, 0xA1, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCB, 0x0C, 0x00, 0x00, + 0xA1, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2C, 0x13, 0x00, 0x00, 0xC7, 0x0C, 0x00, 0x00, + 0xC7, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2F, 0x13, 0x00, 0x00, 0xC9, 0x0C, 0x00, 0x00, 0xC9, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x13, 0x00, 0x00, + 0xCB, 0x0C, 0x00, 0x00, 0xCB, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD4, 0x0C, 0x00, 0x00, 0xB6, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD6, 0x0C, 0x00, 0x00, 0xB6, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, 0x00, + 0xB6, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x36, 0x13, 0x00, 0x00, 0xD4, 0x0C, 0x00, 0x00, + 0xD4, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x39, 0x13, 0x00, 0x00, 0xD6, 0x0C, 0x00, 0x00, 0xD6, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3C, 0x13, 0x00, 0x00, + 0xD8, 0x0C, 0x00, 0x00, 0xD8, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE1, 0x0C, 0x00, 0x00, 0xBD, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE3, 0x0C, 0x00, 0x00, 0xBD, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE5, 0x0C, 0x00, 0x00, + 0xBD, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x40, 0x13, 0x00, 0x00, 0xE1, 0x0C, 0x00, 0x00, + 0xE1, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x43, 0x13, 0x00, 0x00, 0xE3, 0x0C, 0x00, 0x00, 0xE3, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, + 0xE5, 0x0C, 0x00, 0x00, 0xE5, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEE, 0x0C, 0x00, 0x00, 0xC4, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF0, 0x0C, 0x00, 0x00, 0xC4, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF2, 0x0C, 0x00, 0x00, + 0xC4, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4A, 0x13, 0x00, 0x00, 0xEE, 0x0C, 0x00, 0x00, + 0xEE, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4D, 0x13, 0x00, 0x00, 0xF0, 0x0C, 0x00, 0x00, 0xF0, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, + 0xF2, 0x0C, 0x00, 0x00, 0xF2, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFB, 0x0C, 0x00, 0x00, 0xCB, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFD, 0x0C, 0x00, 0x00, 0xCB, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0x0C, 0x00, 0x00, + 0xCB, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x54, 0x13, 0x00, 0x00, 0xFB, 0x0C, 0x00, 0x00, + 0xFB, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x57, 0x13, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5A, 0x13, 0x00, 0x00, + 0xFF, 0x0C, 0x00, 0x00, 0xFF, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, 0xE0, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x0D, 0x00, 0x00, 0xE0, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x0D, 0x00, 0x00, + 0xE0, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5E, 0x13, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, + 0x08, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x61, 0x13, 0x00, 0x00, 0x0A, 0x0D, 0x00, 0x00, 0x0A, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, 0x13, 0x00, 0x00, + 0x0C, 0x0D, 0x00, 0x00, 0x0C, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x15, 0x0D, 0x00, 0x00, 0xE7, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x17, 0x0D, 0x00, 0x00, 0xE7, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x0D, 0x00, 0x00, + 0xE7, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x68, 0x13, 0x00, 0x00, 0x15, 0x0D, 0x00, 0x00, + 0x15, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6B, 0x13, 0x00, 0x00, 0x17, 0x0D, 0x00, 0x00, 0x17, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6E, 0x13, 0x00, 0x00, + 0x19, 0x0D, 0x00, 0x00, 0x19, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, 0xD9, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x31, 0x0D, 0x00, 0x00, 0xD9, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x0D, 0x00, 0x00, + 0xD9, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7C, 0x13, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, + 0x2F, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7F, 0x13, 0x00, 0x00, 0x31, 0x0D, 0x00, 0x00, 0x31, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x82, 0x13, 0x00, 0x00, + 0x33, 0x0D, 0x00, 0x00, 0x33, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3C, 0x0D, 0x00, 0x00, 0xEE, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3E, 0x0D, 0x00, 0x00, 0xEE, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x0D, 0x00, 0x00, + 0xEE, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x86, 0x13, 0x00, 0x00, 0x3C, 0x0D, 0x00, 0x00, + 0x3C, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x89, 0x13, 0x00, 0x00, 0x3E, 0x0D, 0x00, 0x00, 0x3E, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8C, 0x13, 0x00, 0x00, + 0x40, 0x0D, 0x00, 0x00, 0x40, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAA, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x25, 0x13, 0x00, 0x00, 0x2F, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAB, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x07, 0x13, 0x00, 0x00, + 0xAA, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB1, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x39, 0x13, 0x00, 0x00, 0x57, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB2, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xAB, 0x13, 0x00, 0x00, 0xB1, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD4, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x25, 0x13, 0x00, 0x00, + 0x2F, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD5, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x07, 0x13, 0x00, 0x00, 0xD4, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDB, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x39, 0x13, 0x00, 0x00, 0x57, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDC, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xD5, 0x13, 0x00, 0x00, + 0xDB, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFE, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x2F, 0x13, 0x00, 0x00, 0x39, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFF, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x11, 0x13, 0x00, 0x00, 0xFE, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x43, 0x13, 0x00, 0x00, + 0x61, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xFF, 0x13, 0x00, 0x00, 0x05, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x2F, 0x13, 0x00, 0x00, 0x39, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x29, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11, 0x13, 0x00, 0x00, + 0x28, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2F, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x43, 0x13, 0x00, 0x00, 0x61, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x30, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x29, 0x14, 0x00, 0x00, 0x2F, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x4D, 0x13, 0x00, 0x00, + 0x57, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x53, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x2F, 0x13, 0x00, 0x00, 0x52, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x59, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x61, 0x13, 0x00, 0x00, 0x7F, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x53, 0x14, 0x00, 0x00, + 0x59, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7C, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x4D, 0x13, 0x00, 0x00, 0x57, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7D, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x2F, 0x13, 0x00, 0x00, 0x7C, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x83, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x61, 0x13, 0x00, 0x00, + 0x7F, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x84, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x7D, 0x14, 0x00, 0x00, 0x83, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA6, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x57, 0x13, 0x00, 0x00, 0x61, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA7, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x39, 0x13, 0x00, 0x00, + 0xA6, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAD, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x6B, 0x13, 0x00, 0x00, 0x89, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAE, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xA7, 0x14, 0x00, 0x00, 0xAD, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD0, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x57, 0x13, 0x00, 0x00, + 0x61, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD1, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x39, 0x13, 0x00, 0x00, 0xD0, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD7, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x89, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD8, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xD1, 0x14, 0x00, 0x00, + 0xD7, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xF7, 0x14, 0x00, 0x00, 0xDC, 0x13, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xF8, 0x14, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xF7, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF9, 0x14, 0x00, 0x00, 0xF8, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x15, 0x00, 0x00, 0x30, 0x14, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x19, 0x15, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x18, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1A, 0x15, 0x00, 0x00, 0x19, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x39, 0x15, 0x00, 0x00, + 0x84, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x3A, 0x15, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x39, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x15, 0x00, 0x00, + 0x3A, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x5A, 0x15, 0x00, 0x00, 0xD8, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x5B, 0x15, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x5A, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5C, 0x15, 0x00, 0x00, 0x5B, 0x15, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x98, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xDC, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x99, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xB2, 0x13, 0x00, 0x00, 0x98, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9B, 0x0E, 0x00, 0x00, 0x99, 0x0E, 0x00, 0x00, + 0xF9, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x86, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x9B, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB0, 0x0E, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x30, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB1, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x06, 0x14, 0x00, 0x00, 0xB0, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB3, 0x0E, 0x00, 0x00, + 0xB1, 0x0E, 0x00, 0x00, 0x1A, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB9, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xB3, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC8, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x84, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC9, 0x0E, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, + 0xC8, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCB, 0x0E, 0x00, 0x00, 0xC9, 0x0E, 0x00, 0x00, 0x3B, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEC, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xCB, 0x0E, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xD8, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE1, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xAE, 0x14, 0x00, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE3, 0x0E, 0x00, 0x00, 0xE1, 0x0E, 0x00, 0x00, + 0x5C, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1F, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xE3, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x4D, 0x16, 0x00, 0x00, + 0x86, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x4F, 0x16, 0x00, 0x00, 0x4D, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x51, 0x16, 0x00, 0x00, + 0x4F, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x52, 0x16, 0x00, 0x00, 0x51, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x80, 0x16, 0x00, 0x00, + 0xB9, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x82, 0x16, 0x00, 0x00, 0x80, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x84, 0x16, 0x00, 0x00, + 0x82, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x85, 0x16, 0x00, 0x00, 0x84, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB3, 0x16, 0x00, 0x00, + 0xEC, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xB5, 0x16, 0x00, 0x00, 0xB3, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB7, 0x16, 0x00, 0x00, + 0xB5, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB8, 0x16, 0x00, 0x00, 0xB7, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE6, 0x16, 0x00, 0x00, + 0x1F, 0x16, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xE8, 0x16, 0x00, 0x00, 0xE6, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xEA, 0x16, 0x00, 0x00, + 0xE8, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEB, 0x16, 0x00, 0x00, 0xEA, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x00, 0x00, + 0xBD, 0x08, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0D, 0x0F, 0x00, 0x00, 0x52, 0x16, 0x00, 0x00, 0x07, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x0F, 0x00, 0x00, + 0x85, 0x16, 0x00, 0x00, 0x07, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x0F, 0x00, 0x00, 0xB8, 0x16, 0x00, 0x00, + 0x07, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x28, 0x0F, 0x00, 0x00, 0xEB, 0x16, 0x00, 0x00, 0x07, 0x0F, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2E, 0x0F, 0x00, 0x00, + 0x53, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2F, 0x0F, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x2E, 0x0F, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x32, 0x0F, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x0F, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x32, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x34, 0x0F, 0x00, 0x00, 0x2F, 0x0F, 0x00, 0x00, + 0x33, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3B, 0x0F, 0x00, 0x00, 0x2E, 0x0F, 0x00, 0x00, 0x33, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x0F, 0x00, 0x00, + 0x2F, 0x0F, 0x00, 0x00, 0x32, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x47, 0x0F, 0x00, 0x00, 0x2E, 0x0F, 0x00, 0x00, + 0x32, 0x0F, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x0F, 0x00, 0x00, 0xDC, 0x13, 0x00, 0x00, 0xB2, 0x13, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4C, 0x0F, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x4B, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x14, 0x17, 0x00, 0x00, 0x4C, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x15, 0x17, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x14, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x16, 0x17, 0x00, 0x00, 0x15, 0x17, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4F, 0x0F, 0x00, 0x00, + 0x34, 0x0F, 0x00, 0x00, 0x16, 0x17, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x53, 0x0F, 0x00, 0x00, 0x30, 0x14, 0x00, 0x00, + 0x06, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x54, 0x0F, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, 0x53, 0x0F, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1F, 0x17, 0x00, 0x00, + 0x54, 0x0F, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x20, 0x17, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x1F, 0x17, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x17, 0x00, 0x00, + 0x20, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x57, 0x0F, 0x00, 0x00, 0x3B, 0x0F, 0x00, 0x00, 0x21, 0x17, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5B, 0x0F, 0x00, 0x00, + 0x84, 0x14, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5C, 0x0F, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, + 0x5B, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2A, 0x17, 0x00, 0x00, 0x5C, 0x0F, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x2B, 0x17, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x2A, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2C, 0x17, 0x00, 0x00, 0x2B, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5F, 0x0F, 0x00, 0x00, 0x42, 0x0F, 0x00, 0x00, + 0x2C, 0x17, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x63, 0x0F, 0x00, 0x00, 0xD8, 0x14, 0x00, 0x00, 0xAE, 0x14, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, 0x0F, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x63, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x35, 0x17, 0x00, 0x00, 0x64, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x36, 0x17, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x35, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x37, 0x17, 0x00, 0x00, 0x36, 0x17, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x67, 0x0F, 0x00, 0x00, + 0x47, 0x0F, 0x00, 0x00, 0x37, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6D, 0x0F, 0x00, 0x00, 0x0D, 0x0F, 0x00, 0x00, + 0x4F, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x16, 0x0F, 0x00, 0x00, 0x57, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x0F, 0x00, 0x00, + 0x1F, 0x0F, 0x00, 0x00, 0x5F, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x89, 0x0F, 0x00, 0x00, 0x76, 0x0F, 0x00, 0x00, + 0x88, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8B, 0x0F, 0x00, 0x00, 0x89, 0x0F, 0x00, 0x00, 0x4F, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, + 0x28, 0x0F, 0x00, 0x00, 0x67, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA4, 0x0F, 0x00, 0x00, 0x6D, 0x0F, 0x00, 0x00, + 0xA3, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA6, 0x0F, 0x00, 0x00, 0xA4, 0x0F, 0x00, 0x00, 0x57, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC1, 0x0F, 0x00, 0x00, + 0xA4, 0x0F, 0x00, 0x00, 0x5F, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDC, 0x0F, 0x00, 0x00, 0x89, 0x0F, 0x00, 0x00, + 0x67, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3E, 0x19, 0x00, 0x00, 0x6D, 0x0F, 0x00, 0x00, 0x76, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3F, 0x19, 0x00, 0x00, + 0x3E, 0x19, 0x00, 0x00, 0x88, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x00, 0x3F, 0x19, 0x00, 0x00, + 0xA3, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x10, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, + 0x06, 0x10, 0x00, 0x00, 0x8B, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, + 0xA6, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x10, 0x00, 0x00, 0x0A, 0x10, 0x00, 0x00, 0xC1, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, + 0x0C, 0x10, 0x00, 0x00, 0xDC, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x4E, 0x17, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x4F, 0x17, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x4E, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x50, 0x17, 0x00, 0x00, 0x4F, 0x17, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x17, 0x00, 0x00, + 0x50, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x55, 0x17, 0x00, 0x00, 0x53, 0x17, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x57, 0x17, 0x00, 0x00, + 0x55, 0x17, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x58, 0x17, 0x00, 0x00, 0x50, 0x17, 0x00, 0x00, + 0x57, 0x17, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x41, 0x19, 0x00, 0x00, 0x04, 0x13, 0x00, 0x00, 0x22, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x10, 0x00, 0x00, + 0x6D, 0x0F, 0x00, 0x00, 0x41, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, 0x0E, 0x13, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1D, 0x10, 0x00, 0x00, 0x18, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x10, 0x00, 0x00, + 0x40, 0x13, 0x00, 0x00, 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x22, 0x10, 0x00, 0x00, 0x1D, 0x10, 0x00, 0x00, + 0x21, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x26, 0x10, 0x00, 0x00, 0x4A, 0x13, 0x00, 0x00, 0x88, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, + 0x22, 0x10, 0x00, 0x00, 0x26, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x10, 0x00, 0x00, 0x7C, 0x13, 0x00, 0x00, + 0x88, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2C, 0x10, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x2B, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, + 0x68, 0x13, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x2C, 0x10, 0x00, 0x00, + 0x30, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x35, 0x10, 0x00, 0x00, 0x86, 0x13, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, + 0x31, 0x10, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3A, 0x10, 0x00, 0x00, 0x2C, 0x13, 0x00, 0x00, + 0x8B, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3B, 0x10, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x3A, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x00, + 0x36, 0x13, 0x00, 0x00, 0xA6, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x3B, 0x10, 0x00, 0x00, + 0x3F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x44, 0x10, 0x00, 0x00, 0x54, 0x13, 0x00, 0x00, 0xC1, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, 0x5E, 0x13, 0x00, 0x00, + 0xDC, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4A, 0x10, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4C, 0x10, 0x00, 0x00, + 0x4A, 0x10, 0x00, 0x00, 0x58, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x66, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x4C, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x42, 0x19, 0x00, 0x00, 0x07, 0x13, 0x00, 0x00, 0x25, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x10, 0x00, 0x00, + 0x6D, 0x0F, 0x00, 0x00, 0x42, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5A, 0x10, 0x00, 0x00, 0x11, 0x13, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5B, 0x10, 0x00, 0x00, 0x56, 0x10, 0x00, 0x00, 0x5A, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5F, 0x10, 0x00, 0x00, + 0x43, 0x13, 0x00, 0x00, 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, + 0x5F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x64, 0x10, 0x00, 0x00, 0x4D, 0x13, 0x00, 0x00, 0x88, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x65, 0x10, 0x00, 0x00, + 0x60, 0x10, 0x00, 0x00, 0x64, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x69, 0x10, 0x00, 0x00, 0x7F, 0x13, 0x00, 0x00, + 0x88, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6A, 0x10, 0x00, 0x00, 0x65, 0x10, 0x00, 0x00, 0x69, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6E, 0x10, 0x00, 0x00, + 0x6B, 0x13, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6F, 0x10, 0x00, 0x00, 0x6A, 0x10, 0x00, 0x00, + 0x6E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x73, 0x10, 0x00, 0x00, 0x89, 0x13, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00, + 0x6F, 0x10, 0x00, 0x00, 0x73, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x78, 0x10, 0x00, 0x00, 0x2F, 0x13, 0x00, 0x00, + 0x8B, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x79, 0x10, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00, 0x78, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7D, 0x10, 0x00, 0x00, + 0x39, 0x13, 0x00, 0x00, 0xA6, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7E, 0x10, 0x00, 0x00, 0x79, 0x10, 0x00, 0x00, + 0x7D, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x82, 0x10, 0x00, 0x00, 0x57, 0x13, 0x00, 0x00, 0xC1, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, + 0x7E, 0x10, 0x00, 0x00, 0x82, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, 0x61, 0x13, 0x00, 0x00, + 0xDC, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x88, 0x10, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8A, 0x10, 0x00, 0x00, + 0x88, 0x10, 0x00, 0x00, 0x58, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x74, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x8A, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x43, 0x19, 0x00, 0x00, 0x0A, 0x13, 0x00, 0x00, 0x28, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x94, 0x10, 0x00, 0x00, + 0x6D, 0x0F, 0x00, 0x00, 0x43, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x98, 0x10, 0x00, 0x00, 0x14, 0x13, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x99, 0x10, 0x00, 0x00, 0x94, 0x10, 0x00, 0x00, 0x98, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9D, 0x10, 0x00, 0x00, + 0x46, 0x13, 0x00, 0x00, 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9E, 0x10, 0x00, 0x00, 0x99, 0x10, 0x00, 0x00, + 0x9D, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA2, 0x10, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, 0x88, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA3, 0x10, 0x00, 0x00, + 0x9E, 0x10, 0x00, 0x00, 0xA2, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA7, 0x10, 0x00, 0x00, 0x82, 0x13, 0x00, 0x00, + 0x88, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA8, 0x10, 0x00, 0x00, 0xA3, 0x10, 0x00, 0x00, 0xA7, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAC, 0x10, 0x00, 0x00, + 0x6E, 0x13, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAD, 0x10, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, + 0xAC, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB1, 0x10, 0x00, 0x00, 0x8C, 0x13, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, + 0xAD, 0x10, 0x00, 0x00, 0xB1, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB6, 0x10, 0x00, 0x00, 0x32, 0x13, 0x00, 0x00, + 0x8B, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB7, 0x10, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, 0xB6, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBB, 0x10, 0x00, 0x00, + 0x3C, 0x13, 0x00, 0x00, 0xA6, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBC, 0x10, 0x00, 0x00, 0xB7, 0x10, 0x00, 0x00, + 0xBB, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC0, 0x10, 0x00, 0x00, 0x5A, 0x13, 0x00, 0x00, 0xC1, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC1, 0x10, 0x00, 0x00, + 0xBC, 0x10, 0x00, 0x00, 0xC0, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC5, 0x10, 0x00, 0x00, 0x64, 0x13, 0x00, 0x00, + 0xDC, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC6, 0x10, 0x00, 0x00, 0xC1, 0x10, 0x00, 0x00, 0xC5, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC8, 0x10, 0x00, 0x00, + 0xC6, 0x10, 0x00, 0x00, 0x58, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x82, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xC8, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xD7, 0x08, 0x00, 0x00, + 0xD8, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xD8, 0x08, 0x00, 0x00, 0x66, 0x17, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xD7, 0x08, 0x00, 0x00, 0xDA, 0x08, 0x00, 0x00, + 0xC9, 0x08, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xDA, 0x08, 0x00, 0x00, 0x74, 0x17, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xD7, 0x08, 0x00, 0x00, 0xDC, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xDC, 0x08, 0x00, 0x00, + 0x82, 0x17, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xDD, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0xDE, 0x08, 0x00, 0x00, 0xDD, 0x08, 0x00, 0x00, + 0xDD, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xDF, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0xDE, 0x08, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE1, 0x08, 0x00, 0x00, 0xDF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xD8, 0x08, 0x00, 0x00, 0xE1, 0x08, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE3, 0x08, 0x00, 0x00, + 0xDF, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xDA, 0x08, 0x00, 0x00, 0xE3, 0x08, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE5, 0x08, 0x00, 0x00, 0xDF, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xDC, 0x08, 0x00, 0x00, + 0xE5, 0x08, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xD7, 0x08, 0x00, 0x00, + 0xE7, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, 0xE6, 0x08, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xE7, 0x08, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.spv new file mode 100644 index 000000000..b0b7d0836 Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.txt new file mode 100644 index 000000000..d2af1d001 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.txt @@ -0,0 +1,448 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 6468 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeCasResampleConstants "XeCasResampleConstants" + OpMemberName %XeCasResampleConstants 0 "xe_cas_output_offset" + OpMemberName %XeCasResampleConstants 1 "xe_cas_input_output_size_ratio" + OpMemberName %XeCasResampleConstants 2 "xe_cas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeCasResampleConstants 0 Offset 16 + OpMemberDecorate %XeCasResampleConstants 1 Offset 24 + OpMemberDecorate %XeCasResampleConstants 2 Offset 32 + OpDecorate %XeCasResampleConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %uint = OpTypeInt 32 0 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v3float = OpTypeVector %float 3 + %v2uint = OpTypeVector %uint 2 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 + %uint_1 = OpConstant %uint 1 +%uint_532432441 = OpConstant %uint 532432441 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %143 = OpTypeImage %float 2D 0 0 0 1 Unknown + %144 = OpTypeSampledImage %143 +%_ptr_UniformConstant_144 = OpTypePointer UniformConstant %144 + %xe_texture = OpVariable %_ptr_UniformConstant_144 UniformConstant + %int_0 = OpConstant %int 0 + %v4float = OpTypeVector %float 4 + %int_n1 = OpConstant %int -1 + %181 = OpConstantComposite %v2int %int_0 %int_n1 + %int_1 = OpConstant %int 1 + %188 = OpConstantComposite %v2int %int_1 %int_n1 + %194 = OpConstantComposite %v2int %int_n1 %int_0 + %204 = OpConstantComposite %v2int %int_1 %int_0 + %210 = OpConstantComposite %v2int %int_n1 %int_1 + %216 = OpConstantComposite %v2int %int_0 %int_1 + %222 = OpConstantComposite %v2int %int_1 %int_1 + %uint_0 = OpConstant %uint 0 + %uint_2 = OpConstant %uint 2 + %v2float = OpTypeVector %float 2 + %int_2 = OpConstant %int 2 + %712 = OpConstantComposite %v2int %int_2 %int_0 + %734 = OpConstantComposite %v2int %int_0 %int_2 + %745 = OpConstantComposite %v2int %int_2 %int_1 + %751 = OpConstantComposite %v2int %int_1 %int_2 +%float_0_03125 = OpConstant %float 0.03125 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeCasResampleConstants = OpTypeStruct %v2int %v2float %float +%_ptr_PushConstant_XeCasResampleConstants = OpTypePointer PushConstant %XeCasResampleConstants + %_ = OpVariable %_ptr_PushConstant_XeCasResampleConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %float_0_5 = OpConstant %float 0.5 +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %uint_3 = OpConstant %uint 3 + %6461 = OpConstantComposite %v2float %float_0_5 %float_0_5 + %main = OpFunction %void None %3 + %5 = OpLabel + %2205 = OpLoad %v4float %gl_FragCoord + %2206 = OpVectorShuffle %v2float %2205 %2205 0 1 + %2207 = OpConvertFToS %v2int %2206 + %2212 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %2213 = OpLoad %v2int %2212 + %2214 = OpISub %v2int %2207 %2213 + %2215 = OpBitcast %v2uint %2214 + %2218 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_1 + %2219 = OpLoad %v2float %2218 + %2220 = OpBitcast %v2uint %2219 + %2224 = OpVectorTimesScalar %v2float %2219 %float_0_5 + %2226 = OpFSub %v2float %2224 %6461 + %2227 = OpBitcast %v2uint %2226 + %2235 = OpAccessChain %_ptr_PushConstant_float %_ %int_2 + %2236 = OpLoad %float %2235 + %2237 = OpBitcast %uint %2236 + OpBranch %2785 + %2785 = OpLabel + %3136 = OpConvertUToF %v2float %2215 + %3142 = OpBitcast %v2float %2220 + %3143 = OpFMul %v2float %3136 %3142 + %3149 = OpBitcast %v2float %2227 + %3150 = OpFAdd %v2float %3143 %3149 + %3152 = OpExtInst %v2float %1 Floor %3150 + %3155 = OpFSub %v2float %3150 %3152 + %3157 = OpConvertFToS %v2int %3152 + %3162 = OpIAdd %v2int %3157 %181 + %4752 = OpLoad %144 %xe_texture + %4754 = OpImage %143 %4752 + %4755 = OpImageFetch %v4float %4754 %3162 Lod %int_0 + %3165 = OpIAdd %v2int %3157 %194 + %4761 = OpImage %143 %4752 + %4762 = OpImageFetch %v4float %4761 %3165 Lod %int_0 + %4768 = OpImage %143 %4752 + %4769 = OpImageFetch %v4float %4768 %3157 Lod %int_0 + %3170 = OpIAdd %v2int %3157 %188 + %4775 = OpImage %143 %4752 + %4776 = OpImageFetch %v4float %4775 %3170 Lod %int_0 + %3176 = OpIAdd %v2int %3157 %204 + %4789 = OpImage %143 %4752 + %4790 = OpImageFetch %v4float %4789 %3176 Lod %int_0 + %3179 = OpIAdd %v2int %3157 %712 + %4796 = OpImage %143 %4752 + %4797 = OpImageFetch %v4float %4796 %3179 Lod %int_0 + %3182 = OpIAdd %v2int %3157 %210 + %4803 = OpImage %143 %4752 + %4804 = OpImageFetch %v4float %4803 %3182 Lod %int_0 + %3185 = OpIAdd %v2int %3157 %216 + %4810 = OpImage %143 %4752 + %4811 = OpImageFetch %v4float %4810 %3185 Lod %int_0 + %3191 = OpIAdd %v2int %3157 %734 + %4824 = OpImage %143 %4752 + %4825 = OpImageFetch %v4float %4824 %3191 Lod %int_0 + %3194 = OpIAdd %v2int %3157 %222 + %4831 = OpImage %143 %4752 + %4832 = OpImageFetch %v4float %4831 %3194 Lod %int_0 + %3197 = OpIAdd %v2int %3157 %745 + %4838 = OpImage %143 %4752 + %4839 = OpImageFetch %v4float %4838 %3197 Lod %int_0 + %3200 = OpIAdd %v2int %3157 %751 + %4845 = OpImage %143 %4752 + %4846 = OpImageFetch %v4float %4845 %3200 Lod %int_0 + %3219 = OpCompositeExtract %float %4755 0 + %3221 = OpCompositeExtract %float %4755 1 + %3223 = OpCompositeExtract %float %4755 2 + %4868 = OpFMul %float %3219 %3219 + %4871 = OpFMul %float %3221 %3221 + %4874 = OpFMul %float %3223 %3223 + %3232 = OpCompositeExtract %float %4776 0 + %3234 = OpCompositeExtract %float %4776 1 + %3236 = OpCompositeExtract %float %4776 2 + %4878 = OpFMul %float %3232 %3232 + %4881 = OpFMul %float %3234 %3234 + %4884 = OpFMul %float %3236 %3236 + %3258 = OpCompositeExtract %float %4762 0 + %3260 = OpCompositeExtract %float %4762 1 + %3262 = OpCompositeExtract %float %4762 2 + %4898 = OpFMul %float %3258 %3258 + %4901 = OpFMul %float %3260 %3260 + %4904 = OpFMul %float %3262 %3262 + %3271 = OpCompositeExtract %float %4769 0 + %3273 = OpCompositeExtract %float %4769 1 + %3275 = OpCompositeExtract %float %4769 2 + %4908 = OpFMul %float %3271 %3271 + %4911 = OpFMul %float %3273 %3273 + %4914 = OpFMul %float %3275 %3275 + %3284 = OpCompositeExtract %float %4790 0 + %3286 = OpCompositeExtract %float %4790 1 + %3288 = OpCompositeExtract %float %4790 2 + %4918 = OpFMul %float %3284 %3284 + %4921 = OpFMul %float %3286 %3286 + %4924 = OpFMul %float %3288 %3288 + %3297 = OpCompositeExtract %float %4797 0 + %3299 = OpCompositeExtract %float %4797 1 + %3301 = OpCompositeExtract %float %4797 2 + %4928 = OpFMul %float %3297 %3297 + %4931 = OpFMul %float %3299 %3299 + %4934 = OpFMul %float %3301 %3301 + %3310 = OpCompositeExtract %float %4804 0 + %3312 = OpCompositeExtract %float %4804 1 + %3314 = OpCompositeExtract %float %4804 2 + %4938 = OpFMul %float %3310 %3310 + %4941 = OpFMul %float %3312 %3312 + %4944 = OpFMul %float %3314 %3314 + %3323 = OpCompositeExtract %float %4811 0 + %3325 = OpCompositeExtract %float %4811 1 + %3327 = OpCompositeExtract %float %4811 2 + %4948 = OpFMul %float %3323 %3323 + %4951 = OpFMul %float %3325 %3325 + %4954 = OpFMul %float %3327 %3327 + %3336 = OpCompositeExtract %float %4832 0 + %3338 = OpCompositeExtract %float %4832 1 + %3340 = OpCompositeExtract %float %4832 2 + %4958 = OpFMul %float %3336 %3336 + %4961 = OpFMul %float %3338 %3338 + %4964 = OpFMul %float %3340 %3340 + %3349 = OpCompositeExtract %float %4839 0 + %3351 = OpCompositeExtract %float %4839 1 + %3353 = OpCompositeExtract %float %4839 2 + %4968 = OpFMul %float %3349 %3349 + %4971 = OpFMul %float %3351 %3351 + %4974 = OpFMul %float %3353 %3353 + %3375 = OpCompositeExtract %float %4825 0 + %3377 = OpCompositeExtract %float %4825 1 + %3379 = OpCompositeExtract %float %4825 2 + %4988 = OpFMul %float %3375 %3375 + %4991 = OpFMul %float %3377 %3377 + %4994 = OpFMul %float %3379 %3379 + %3388 = OpCompositeExtract %float %4846 0 + %3390 = OpCompositeExtract %float %4846 1 + %3392 = OpCompositeExtract %float %4846 2 + %4998 = OpFMul %float %3388 %3388 + %5001 = OpFMul %float %3390 %3390 + %5004 = OpFMul %float %3392 %3392 + %5034 = OpExtInst %float %1 FMin %4901 %4911 + %5035 = OpExtInst %float %1 FMin %4871 %5034 + %5041 = OpExtInst %float %1 FMin %4921 %4951 + %5042 = OpExtInst %float %1 FMin %5035 %5041 + %5076 = OpExtInst %float %1 FMax %4901 %4911 + %5077 = OpExtInst %float %1 FMax %4871 %5076 + %5083 = OpExtInst %float %1 FMax %4921 %4951 + %5084 = OpExtInst %float %1 FMax %5077 %5083 + %5118 = OpExtInst %float %1 FMin %4911 %4921 + %5119 = OpExtInst %float %1 FMin %4881 %5118 + %5125 = OpExtInst %float %1 FMin %4931 %4961 + %5126 = OpExtInst %float %1 FMin %5119 %5125 + %5160 = OpExtInst %float %1 FMax %4911 %4921 + %5161 = OpExtInst %float %1 FMax %4881 %5160 + %5167 = OpExtInst %float %1 FMax %4931 %4961 + %5168 = OpExtInst %float %1 FMax %5161 %5167 + %5202 = OpExtInst %float %1 FMin %4941 %4951 + %5203 = OpExtInst %float %1 FMin %4911 %5202 + %5209 = OpExtInst %float %1 FMin %4961 %4991 + %5210 = OpExtInst %float %1 FMin %5203 %5209 + %5244 = OpExtInst %float %1 FMax %4941 %4951 + %5245 = OpExtInst %float %1 FMax %4911 %5244 + %5251 = OpExtInst %float %1 FMax %4961 %4991 + %5252 = OpExtInst %float %1 FMax %5245 %5251 + %5286 = OpExtInst %float %1 FMin %4951 %4961 + %5287 = OpExtInst %float %1 FMin %4921 %5286 + %5293 = OpExtInst %float %1 FMin %4971 %5001 + %5294 = OpExtInst %float %1 FMin %5287 %5293 + %5328 = OpExtInst %float %1 FMax %4951 %4961 + %5329 = OpExtInst %float %1 FMax %4921 %5328 + %5335 = OpExtInst %float %1 FMax %4971 %5001 + %5336 = OpExtInst %float %1 FMax %5329 %5335 + %5367 = OpBitcast %uint %5084 + %5368 = OpISub %uint %uint_2129690299 %5367 + %5369 = OpBitcast %float %5368 + %5400 = OpBitcast %uint %5168 + %5401 = OpISub %uint %uint_2129690299 %5400 + %5402 = OpBitcast %float %5401 + %5433 = OpBitcast %uint %5252 + %5434 = OpISub %uint %uint_2129690299 %5433 + %5435 = OpBitcast %float %5434 + %5466 = OpBitcast %uint %5336 + %5467 = OpISub %uint %uint_2129690299 %5466 + %5468 = OpBitcast %float %5467 + %3736 = OpFSub %float %float_1 %5084 + %3737 = OpExtInst %float %1 FMin %5042 %3736 + %3739 = OpFMul %float %3737 %5369 + %5510 = OpExtInst %float %1 FClamp %3739 %float_0 %float_1 + %3760 = OpFSub %float %float_1 %5168 + %3761 = OpExtInst %float %1 FMin %5126 %3760 + %3763 = OpFMul %float %3761 %5402 + %5561 = OpExtInst %float %1 FClamp %3763 %float_0 %float_1 + %3784 = OpFSub %float %float_1 %5252 + %3785 = OpExtInst %float %1 FMin %5210 %3784 + %3787 = OpFMul %float %3785 %5435 + %5612 = OpExtInst %float %1 FClamp %3787 %float_0 %float_1 + %3808 = OpFSub %float %float_1 %5336 + %3809 = OpExtInst %float %1 FMin %5294 %3808 + %3811 = OpFMul %float %3809 %5468 + %5663 = OpExtInst %float %1 FClamp %3811 %float_0 %float_1 + %5709 = OpBitcast %uint %5510 + %5711 = OpShiftRightLogical %uint %5709 %uint_1 + %5713 = OpIAdd %uint %5711 %uint_532432441 + %5714 = OpBitcast %float %5713 + %5760 = OpBitcast %uint %5561 + %5762 = OpShiftRightLogical %uint %5760 %uint_1 + %5764 = OpIAdd %uint %5762 %uint_532432441 + %5765 = OpBitcast %float %5764 + %5811 = OpBitcast %uint %5612 + %5813 = OpShiftRightLogical %uint %5811 %uint_1 + %5815 = OpIAdd %uint %5813 %uint_532432441 + %5816 = OpBitcast %float %5815 + %5862 = OpBitcast %uint %5663 + %5864 = OpShiftRightLogical %uint %5862 %uint_1 + %5866 = OpIAdd %uint %5864 %uint_532432441 + %5867 = OpBitcast %float %5866 + %3847 = OpBitcast %float %2237 + %3853 = OpFMul %float %5714 %3847 + %3862 = OpFMul %float %5765 %3847 + %3871 = OpFMul %float %5816 %3847 + %3880 = OpFMul %float %5867 %3847 + %3886 = OpCompositeExtract %float %3155 0 + %3887 = OpFSub %float %float_1 %3886 + %3890 = OpCompositeExtract %float %3155 1 + %3891 = OpFSub %float %float_1 %3890 + %3892 = OpFMul %float %3887 %3891 + %3899 = OpFMul %float %3886 %3891 + %3906 = OpFMul %float %3887 %3890 + %3911 = OpFMul %float %3886 %3890 + %3915 = OpFSub %float %5084 %5042 + %3916 = OpFAdd %float %float_0_03125 %3915 + %5908 = OpBitcast %uint %3916 + %5909 = OpISub %uint %uint_2129690299 %5908 + %5910 = OpBitcast %float %5909 + %3919 = OpFMul %float %3892 %5910 + %3923 = OpFSub %float %5168 %5126 + %3924 = OpFAdd %float %float_0_03125 %3923 + %5919 = OpBitcast %uint %3924 + %5920 = OpISub %uint %uint_2129690299 %5919 + %5921 = OpBitcast %float %5920 + %3927 = OpFMul %float %3899 %5921 + %3931 = OpFSub %float %5252 %5210 + %3932 = OpFAdd %float %float_0_03125 %3931 + %5930 = OpBitcast %uint %3932 + %5931 = OpISub %uint %uint_2129690299 %5930 + %5932 = OpBitcast %float %5931 + %3935 = OpFMul %float %3906 %5932 + %3939 = OpFSub %float %5336 %5294 + %3940 = OpFAdd %float %float_0_03125 %3939 + %5941 = OpBitcast %uint %3940 + %5942 = OpISub %uint %uint_2129690299 %5941 + %5943 = OpBitcast %float %5942 + %3943 = OpFMul %float %3911 %5943 + %3949 = OpFMul %float %3853 %3919 + %3958 = OpFMul %float %3862 %3927 + %3976 = OpFMul %float %3871 %3935 + %3977 = OpFAdd %float %3958 %3976 + %3979 = OpFAdd %float %3977 %3919 + %4003 = OpFMul %float %3880 %3943 + %4004 = OpFAdd %float %3949 %4003 + %4006 = OpFAdd %float %4004 %3927 + %4033 = OpFAdd %float %4004 %3935 + %4060 = OpFAdd %float %3977 %3943 + %6462 = OpFAdd %float %3949 %3958 + %6463 = OpFAdd %float %6462 %3976 + %6464 = OpFAdd %float %6463 %4003 + %4102 = OpFMul %float %float_2 %6464 + %4104 = OpFAdd %float %4102 %3979 + %4106 = OpFAdd %float %4104 %4006 + %4108 = OpFAdd %float %4106 %4033 + %4110 = OpFAdd %float %4108 %4060 + %5966 = OpBitcast %uint %4110 + %5967 = OpISub %uint %uint_2129764351 %5966 + %5968 = OpBitcast %float %5967 + %5971 = OpFNegate %float %5968 + %5973 = OpFMul %float %5971 %4110 + %5975 = OpFAdd %float %5973 %float_2 + %5976 = OpFMul %float %5968 %5975 + %6465 = OpFAdd %float %4868 %4898 + %4120 = OpFMul %float %3949 %6465 + %4124 = OpFMul %float %4878 %3958 + %4125 = OpFAdd %float %4120 %4124 + %4129 = OpFMul %float %4928 %3958 + %4130 = OpFAdd %float %4125 %4129 + %4134 = OpFMul %float %4938 %3976 + %4135 = OpFAdd %float %4130 %4134 + %4139 = OpFMul %float %4988 %3976 + %4140 = OpFAdd %float %4135 %4139 + %4144 = OpFMul %float %4968 %4003 + %4145 = OpFAdd %float %4140 %4144 + %4149 = OpFMul %float %4998 %4003 + %4150 = OpFAdd %float %4145 %4149 + %4154 = OpFMul %float %4908 %3979 + %4155 = OpFAdd %float %4150 %4154 + %4159 = OpFMul %float %4918 %4006 + %4160 = OpFAdd %float %4155 %4159 + %4164 = OpFMul %float %4948 %4033 + %4165 = OpFAdd %float %4160 %4164 + %4169 = OpFMul %float %4958 %4060 + %4170 = OpFAdd %float %4165 %4169 + %4172 = OpFMul %float %4170 %5976 + %5990 = OpExtInst %float %1 FClamp %4172 %float_0 %float_1 + %6466 = OpFAdd %float %4871 %4901 + %4182 = OpFMul %float %3949 %6466 + %4186 = OpFMul %float %4881 %3958 + %4187 = OpFAdd %float %4182 %4186 + %4191 = OpFMul %float %4931 %3958 + %4192 = OpFAdd %float %4187 %4191 + %4196 = OpFMul %float %4941 %3976 + %4197 = OpFAdd %float %4192 %4196 + %4201 = OpFMul %float %4991 %3976 + %4202 = OpFAdd %float %4197 %4201 + %4206 = OpFMul %float %4971 %4003 + %4207 = OpFAdd %float %4202 %4206 + %4211 = OpFMul %float %5001 %4003 + %4212 = OpFAdd %float %4207 %4211 + %4216 = OpFMul %float %4911 %3979 + %4217 = OpFAdd %float %4212 %4216 + %4221 = OpFMul %float %4921 %4006 + %4222 = OpFAdd %float %4217 %4221 + %4226 = OpFMul %float %4951 %4033 + %4227 = OpFAdd %float %4222 %4226 + %4231 = OpFMul %float %4961 %4060 + %4232 = OpFAdd %float %4227 %4231 + %4234 = OpFMul %float %4232 %5976 + %6004 = OpExtInst %float %1 FClamp %4234 %float_0 %float_1 + %6467 = OpFAdd %float %4874 %4904 + %4244 = OpFMul %float %3949 %6467 + %4248 = OpFMul %float %4884 %3958 + %4249 = OpFAdd %float %4244 %4248 + %4253 = OpFMul %float %4934 %3958 + %4254 = OpFAdd %float %4249 %4253 + %4258 = OpFMul %float %4944 %3976 + %4259 = OpFAdd %float %4254 %4258 + %4263 = OpFMul %float %4994 %3976 + %4264 = OpFAdd %float %4259 %4263 + %4268 = OpFMul %float %4974 %4003 + %4269 = OpFAdd %float %4264 %4268 + %4273 = OpFMul %float %5004 %4003 + %4274 = OpFAdd %float %4269 %4273 + %4278 = OpFMul %float %4914 %3979 + %4279 = OpFAdd %float %4274 %4278 + %4283 = OpFMul %float %4924 %4006 + %4284 = OpFAdd %float %4279 %4283 + %4288 = OpFMul %float %4954 %4033 + %4289 = OpFAdd %float %4284 %4288 + %4293 = OpFMul %float %4964 %4060 + %4294 = OpFAdd %float %4289 %4293 + %4296 = OpFMul %float %4294 %5976 + %6018 = OpExtInst %float %1 FClamp %4296 %float_0 %float_1 + %2264 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %2264 %5990 + %2266 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %2266 %6004 + %2268 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %2268 %6018 + %2269 = OpLoad %v4float %xe_frag_color + %2270 = OpVectorShuffle %v3float %2269 %2269 0 1 2 + %2271 = OpExtInst %v3float %1 Sqrt %2270 + %2273 = OpCompositeExtract %float %2271 0 + OpStore %2264 %2273 + %2275 = OpCompositeExtract %float %2271 1 + OpStore %2266 %2275 + %2277 = OpCompositeExtract %float %2271 2 + OpStore %2268 %2277 + %2279 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %2279 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h new file mode 100644 index 000000000..82cf26c00 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h @@ -0,0 +1,1196 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_cas_sharpen_dither.frag +const uint8_t guest_output_ffx_cas_sharpen_dither_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x7B, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x58, 0x65, 0x43, 0x61, 0x73, 0x53, 0x68, 0x61, + 0x72, 0x70, 0x65, 0x6E, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, + 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x6F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x73, + 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 0x73, 0x5F, 0x70, 0x6F, 0x73, + 0x74, 0x5F, 0x73, 0x65, 0x74, 0x75, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, + 0xBA, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, + 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xAB, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xB4, 0x09, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0xB8, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xD0, 0x09, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, + 0x84, 0x83, 0x83, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0xE7, 0xE6, 0x66, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0xCC, 0xCB, 0xCB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x9F, 0x9E, 0x1E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x8C, 0x8B, 0x8B, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0xB6, 0xB5, 0xB5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0x87, 0x86, 0x06, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5B, 0x00, 0x00, 0x00, 0xA0, 0x9F, 0x9F, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xD2, 0xD1, 0xD1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, + 0x9B, 0x9A, 0x1A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5E, 0x00, 0x00, 0x00, 0x95, 0x94, 0x94, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x92, 0x91, 0x91, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xBA, 0xB9, 0xB9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0xBE, 0xBD, 0xBD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x8F, 0x8E, 0x0E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, + 0x89, 0x88, 0x08, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, + 0x8A, 0x89, 0x89, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0xA3, 0xA2, 0x22, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0xFD, 0xFC, 0xFC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0xF6, 0xF5, 0xF5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6A, 0x00, 0x00, 0x00, 0x90, 0x8F, 0x8F, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xD1, 0xD0, 0xD0, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x8B, 0x8A, 0x0A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6D, 0x00, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0xFE, 0xFD, 0xFD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0xB7, 0xB6, 0x36, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0x38, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0xBB, 0xBA, 0x3A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xAC, 0xAB, 0xAB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x00, 0x00, 0x90, 0x8F, 0x8F, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, + 0xE6, 0xE5, 0xE5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0xC2, 0xC1, 0xC1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0xA1, 0xA0, 0x20, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x00, 0xCF, 0xCE, 0x4E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0x9D, 0x9C, 0x9C, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x82, 0x81, 0x81, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0xB9, 0xB8, 0x38, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xD0, 0xCF, 0xCF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, + 0xB5, 0xB4, 0xB4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x00, 0x00, 0xF4, 0xF3, 0xF3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xE7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0xE3, 0xE2, 0x62, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0xEB, 0xEA, 0x6A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, + 0xF3, 0xF2, 0x72, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0xC8, 0xC7, 0xC7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, + 0xAA, 0xA9, 0xA9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8B, 0x00, 0x00, 0x00, 0xD3, 0xD2, 0x52, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0xC0, 0xBF, 0xBF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, + 0xEC, 0xEB, 0xEB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x00, 0x00, 0xDF, 0xDE, 0x5E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xDF, 0xDE, 0x5E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0xED, 0xEC, 0xEC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x91, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0xF9, 0xF8, 0x78, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0xC9, 0xC8, 0x48, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xD2, 0xD1, 0xD1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x86, 0x85, 0x85, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, + 0xD5, 0xD4, 0xD4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0xD9, 0xD8, 0x58, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0xD0, 0xCF, 0xCF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, + 0xAB, 0xAA, 0x2A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9D, 0x00, 0x00, 0x00, 0x91, 0x90, 0x90, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0xDD, 0xDC, 0xDC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, + 0xD8, 0xD7, 0xD7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA0, 0x00, 0x00, 0x00, 0xB4, 0xB3, 0xB3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, + 0xAF, 0xAE, 0x2E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x9C, 0x9B, 0x9B, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xBE, 0xBD, 0xBD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, + 0x97, 0x96, 0x16, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA6, 0x00, 0x00, 0x00, 0xF8, 0xF7, 0xF7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0xC7, 0xC6, 0x46, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, + 0xAA, 0xA9, 0xA9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA9, 0x00, 0x00, 0x00, 0xFC, 0xFB, 0xFB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, + 0x88, 0x87, 0x87, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xF4, 0xF3, 0xF3, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0x9E, 0x9D, 0x9D, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAF, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0xB4, 0xB3, 0xB3, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0xD6, 0xD5, 0xD5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xF1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0xBF, 0xBE, 0x3E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, + 0xEF, 0xEE, 0x6E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0xEE, 0xED, 0xED, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, + 0xC5, 0xC4, 0xC4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0xD1, 0xD0, 0xD0, 0x38, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xC3, 0xC2, 0x42, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, + 0x9A, 0x99, 0x99, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x91, 0x90, 0x90, 0x38, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0xC4, 0xC3, 0xC3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, + 0xFF, 0xFE, 0x7E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFB, 0xFA, 0x7A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xFE, 0xFD, 0xFD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x8B, 0x8A, 0x0A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0xE1, 0xE0, 0x60, 0x38, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0x8D, 0x8C, 0x8C, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC4, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0xB7, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0xA5, 0xA4, 0xA4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, + 0x83, 0x82, 0x02, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCA, 0x00, 0x00, 0x00, 0x9C, 0x9B, 0x9B, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0xCB, 0xCA, 0x4A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0xB0, 0xAF, 0xAF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCD, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xC2, 0xC1, 0xC1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, + 0x89, 0x88, 0x08, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD0, 0x00, 0x00, 0x00, 0xCB, 0xCA, 0x4A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xCD, 0xCC, 0xCC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD3, 0x00, 0x00, 0x00, 0xFB, 0xFA, 0x7A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, + 0xCA, 0xC9, 0xC9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD6, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x32, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, + 0xDC, 0xDB, 0xDB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD9, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0xDD, 0xDC, 0xDC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, + 0xEA, 0xE9, 0xE9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDC, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xA3, 0xA2, 0x22, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, + 0xDA, 0xD9, 0xD9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDF, 0x00, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, + 0x8E, 0x8D, 0x8D, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE2, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xE7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0xCF, 0xCE, 0x4E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, + 0xEA, 0xE9, 0xE9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE5, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x32, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x82, 0x81, 0x81, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0xAE, 0xAD, 0xAD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE8, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0xC6, 0xC5, 0xC5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, + 0xAD, 0xAC, 0xAC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, + 0xD4, 0xD3, 0xD3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0x98, 0x97, 0x97, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0xE5, 0xE4, 0xE4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF1, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0xC4, 0xC3, 0xC3, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, + 0x96, 0x95, 0x95, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF4, 0x00, 0x00, 0x00, 0xB1, 0xB0, 0xB0, 0x38, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0xF8, 0xF7, 0xF7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, + 0xB8, 0xB7, 0xB7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF7, 0x00, 0x00, 0x00, 0x93, 0x92, 0x12, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0xF0, 0xF0, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, + 0xA6, 0xA5, 0xA5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xAE, 0xAD, 0xAD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xC7, 0xC6, 0x46, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xB2, 0xB1, 0xB1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0xC0, 0xBF, 0xBF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0xBD, 0xBC, 0xBC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x8F, 0x8E, 0x0E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x94, 0x93, 0x93, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, + 0x85, 0x84, 0x84, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x01, 0x00, 0x00, 0x93, 0x92, 0x12, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0xEE, 0xED, 0xED, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0xE2, 0xE1, 0xE1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x01, 0x00, 0x00, 0x98, 0x97, 0x97, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0xC3, 0xC2, 0x42, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, + 0xCE, 0xCD, 0xCD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0C, 0x01, 0x00, 0x00, 0xF1, 0xF0, 0xF0, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0xA0, 0x9F, 0x9F, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, + 0xF0, 0xEF, 0xEF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0xC1, 0xC0, 0xC0, 0x37, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0xFC, 0xFB, 0xFB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, + 0xE4, 0xE3, 0xE3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x12, 0x01, 0x00, 0x00, 0xBB, 0xBA, 0x3A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0xE0, 0xDF, 0xDF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x01, 0x00, 0x00, 0xA2, 0xA1, 0xA1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0xD9, 0xD8, 0x58, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, + 0x8A, 0x89, 0x89, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x18, 0x01, 0x00, 0x00, 0xBF, 0xBE, 0x3E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, + 0xA5, 0xA4, 0xA4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1B, 0x01, 0x00, 0x00, 0xFD, 0xFC, 0xFC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1D, 0x01, 0x00, 0x00, + 0xF7, 0xF6, 0x76, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1E, 0x01, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0x86, 0x85, 0x85, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x21, 0x01, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0xC1, 0xC0, 0xC0, 0xB7, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, + 0xA8, 0xA7, 0xA7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0xD3, 0xD2, 0x52, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0xEB, 0xEA, 0x6A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, + 0xBC, 0xBB, 0xBB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x27, 0x01, 0x00, 0x00, 0x9F, 0x9E, 0x1E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0xB1, 0xB0, 0xB0, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, + 0xEF, 0xEE, 0x6E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0xA7, 0xA6, 0x26, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2D, 0x01, 0x00, 0x00, 0xC6, 0xC5, 0xC5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, 0xD7, 0xD6, 0x56, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, + 0xA4, 0xA3, 0xA3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x85, 0x84, 0x84, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0xC8, 0xC7, 0xC7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, + 0x94, 0x93, 0x93, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x33, 0x01, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0xFA, 0xF9, 0xF9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x36, 0x01, 0x00, 0x00, 0xB6, 0xB5, 0xB5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0x92, 0x91, 0x91, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, + 0xD4, 0xD3, 0xD3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x39, 0x01, 0x00, 0x00, 0xE7, 0xE6, 0x66, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x99, 0x98, 0x18, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, + 0x8E, 0x8D, 0x8D, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3C, 0x01, 0x00, 0x00, 0xE1, 0xE0, 0x60, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3D, 0x01, 0x00, 0x00, 0x95, 0x94, 0x94, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, + 0xDE, 0xDD, 0xDD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3F, 0x01, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x87, 0x86, 0x06, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, + 0xA9, 0xA8, 0x28, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x42, 0x01, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, + 0xA7, 0xA6, 0x26, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x45, 0x01, 0x00, 0x00, 0x81, 0x80, 0x00, 0x37, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, + 0xE9, 0xE8, 0x68, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x48, 0x01, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, + 0xD5, 0xD4, 0xD4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4B, 0x01, 0x00, 0x00, 0xA2, 0xA1, 0xA1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4D, 0x01, 0x00, 0x00, + 0xF7, 0xF6, 0x76, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4E, 0x01, 0x00, 0x00, 0xD7, 0xD6, 0x56, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, 0xF2, 0xF1, 0xF1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0xF5, 0xF4, 0xF4, 0x39, 0x2C, 0x00, 0x03, 0x01, 0x50, 0x00, 0x00, 0x00, + 0x51, 0x01, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x59, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, + 0x6B, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, + 0x6E, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, + 0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, + 0x7A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x7D, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, + 0x86, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, + 0x8C, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00, + 0x9E, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, + 0xA1, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xA4, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, + 0xA7, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, + 0xAA, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, + 0xAD, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, + 0xB0, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, + 0xB3, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, + 0xB6, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, + 0xB9, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, + 0xC5, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, + 0xCB, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, + 0xCE, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, + 0xD1, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, + 0xD4, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, + 0xD7, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, + 0xDA, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, + 0xDD, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, + 0xE3, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, + 0xE6, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, + 0xE9, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, + 0xEC, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, + 0xF2, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, + 0xF5, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, + 0xFB, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, + 0x07, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, + 0x0A, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, + 0x0D, 0x01, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, + 0x13, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, + 0x16, 0x01, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, + 0x1C, 0x01, 0x00, 0x00, 0x1D, 0x01, 0x00, 0x00, 0x1E, 0x01, 0x00, 0x00, + 0x1F, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, + 0x22, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, + 0x25, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, + 0x28, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x2B, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x2D, 0x01, 0x00, 0x00, + 0x2E, 0x01, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, + 0x31, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, + 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, + 0x37, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, + 0x3A, 0x01, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, + 0x3D, 0x01, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, 0x3F, 0x01, 0x00, 0x00, + 0x40, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, + 0x43, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, + 0x46, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, + 0x49, 0x01, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, 0x4B, 0x01, 0x00, 0x00, + 0x4C, 0x01, 0x00, 0x00, 0x4D, 0x01, 0x00, 0x00, 0x4E, 0x01, 0x00, 0x00, + 0x4F, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x57, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x5B, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x39, 0x46, 0xBC, 0x1F, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x95, 0x01, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x19, 0x00, 0x09, 0x00, 0xA8, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x03, 0x00, 0xA9, 0x01, 0x00, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xA9, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xAA, 0x01, 0x00, 0x00, + 0xAB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0xC7, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0xC7, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0xC7, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xDB, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xE5, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xEB, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xF1, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xF7, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xF6, 0x03, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x20, 0x00, 0x04, 0x00, + 0xB3, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xB3, 0x09, 0x00, 0x00, 0xB4, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xB9, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xB9, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xBB, 0x09, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xC4, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xCF, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xCF, 0x09, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xDE, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0xF4, 0x09, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFD, 0x09, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x7A, 0x1A, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x5B, 0x01, 0x00, 0x00, + 0xA0, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xB5, 0x09, 0x00, 0x00, 0xB4, 0x09, 0x00, 0x00, + 0x4F, 0x00, 0x07, 0x00, 0x9E, 0x03, 0x00, 0x00, 0xB6, 0x09, 0x00, 0x00, + 0xB5, 0x09, 0x00, 0x00, 0xB5, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xB7, 0x09, 0x00, 0x00, 0xB6, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xBB, 0x09, 0x00, 0x00, 0xBC, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xBD, 0x09, 0x00, 0x00, 0xBC, 0x09, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xBE, 0x09, 0x00, 0x00, 0xB7, 0x09, 0x00, 0x00, + 0xBD, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xBF, 0x09, 0x00, 0x00, 0xBE, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC4, 0x09, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC6, 0x09, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC7, 0x09, 0x00, 0x00, 0xC6, 0x09, 0x00, 0x00, + 0xF9, 0x00, 0x02, 0x00, 0xF8, 0x0B, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0xF8, 0x0B, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x57, 0x0D, 0x00, 0x00, 0xBF, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x67, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x57, 0x0D, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x6A, 0x0D, 0x00, 0x00, 0x57, 0x0D, 0x00, 0x00, + 0x67, 0x0D, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x6C, 0x0D, 0x00, 0x00, 0x67, 0x0D, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x71, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0xCE, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xA9, 0x01, 0x00, 0x00, + 0xA7, 0x13, 0x00, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xA9, 0x13, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xAA, 0x13, 0x00, 0x00, + 0xA9, 0x13, 0x00, 0x00, 0x71, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x74, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, 0xDB, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, + 0xA7, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xB1, 0x13, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, 0x74, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xB7, 0x13, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, + 0xB7, 0x13, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x79, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xBE, 0x13, 0x00, 0x00, + 0xA7, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xBF, 0x13, 0x00, 0x00, 0xBE, 0x13, 0x00, 0x00, 0x79, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x7F, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0xE5, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xCC, 0x13, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xCD, 0x13, 0x00, 0x00, 0xCC, 0x13, 0x00, 0x00, + 0x7F, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x82, 0x0D, 0x00, 0x00, + 0x6C, 0x0D, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xD3, 0x13, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xD4, 0x13, 0x00, 0x00, + 0xD3, 0x13, 0x00, 0x00, 0x82, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x85, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, 0xEB, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xDA, 0x13, 0x00, 0x00, + 0xA7, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xDB, 0x13, 0x00, 0x00, 0xDA, 0x13, 0x00, 0x00, 0x85, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x88, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0xF1, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xE1, 0x13, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xE2, 0x13, 0x00, 0x00, 0xE1, 0x13, 0x00, 0x00, + 0x88, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x8E, 0x0D, 0x00, 0x00, + 0x6C, 0x0D, 0x00, 0x00, 0xF6, 0x03, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xEF, 0x13, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xF0, 0x13, 0x00, 0x00, + 0xEF, 0x13, 0x00, 0x00, 0x8E, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x91, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, 0xF7, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xF6, 0x13, 0x00, 0x00, + 0xA7, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xF7, 0x13, 0x00, 0x00, 0xF6, 0x13, 0x00, 0x00, 0x91, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x94, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xFD, 0x13, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xFE, 0x13, 0x00, 0x00, 0xFD, 0x13, 0x00, 0x00, + 0x94, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x97, 0x0D, 0x00, 0x00, + 0x6C, 0x0D, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x05, 0x14, 0x00, 0x00, + 0x04, 0x14, 0x00, 0x00, 0x97, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAA, 0x0D, 0x00, 0x00, 0xAA, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAC, 0x0D, 0x00, 0x00, + 0xAA, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAE, 0x0D, 0x00, 0x00, 0xAA, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1B, 0x14, 0x00, 0x00, 0xAA, 0x0D, 0x00, 0x00, 0xAA, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x14, 0x00, 0x00, + 0xAC, 0x0D, 0x00, 0x00, 0xAC, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x21, 0x14, 0x00, 0x00, 0xAE, 0x0D, 0x00, 0x00, + 0xAE, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB7, 0x0D, 0x00, 0x00, 0xBF, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB9, 0x0D, 0x00, 0x00, + 0xBF, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBB, 0x0D, 0x00, 0x00, 0xBF, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x25, 0x14, 0x00, 0x00, 0xB7, 0x0D, 0x00, 0x00, 0xB7, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, + 0xB9, 0x0D, 0x00, 0x00, 0xB9, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2B, 0x14, 0x00, 0x00, 0xBB, 0x0D, 0x00, 0x00, + 0xBB, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD1, 0x0D, 0x00, 0x00, 0xB1, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD3, 0x0D, 0x00, 0x00, + 0xB1, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD5, 0x0D, 0x00, 0x00, 0xB1, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x39, 0x14, 0x00, 0x00, 0xD1, 0x0D, 0x00, 0x00, 0xD1, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3C, 0x14, 0x00, 0x00, + 0xD3, 0x0D, 0x00, 0x00, 0xD3, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3F, 0x14, 0x00, 0x00, 0xD5, 0x0D, 0x00, 0x00, + 0xD5, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDE, 0x0D, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE0, 0x0D, 0x00, 0x00, + 0xB8, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE2, 0x0D, 0x00, 0x00, 0xB8, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x43, 0x14, 0x00, 0x00, 0xDE, 0x0D, 0x00, 0x00, 0xDE, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x46, 0x14, 0x00, 0x00, + 0xE0, 0x0D, 0x00, 0x00, 0xE0, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x49, 0x14, 0x00, 0x00, 0xE2, 0x0D, 0x00, 0x00, + 0xE2, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEB, 0x0D, 0x00, 0x00, 0xCD, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xED, 0x0D, 0x00, 0x00, + 0xCD, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, 0xCD, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4D, 0x14, 0x00, 0x00, 0xEB, 0x0D, 0x00, 0x00, 0xEB, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, + 0xED, 0x0D, 0x00, 0x00, 0xED, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x53, 0x14, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, + 0xEF, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF8, 0x0D, 0x00, 0x00, 0xD4, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFA, 0x0D, 0x00, 0x00, + 0xD4, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFC, 0x0D, 0x00, 0x00, 0xD4, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x57, 0x14, 0x00, 0x00, 0xF8, 0x0D, 0x00, 0x00, 0xF8, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, + 0xFA, 0x0D, 0x00, 0x00, 0xFA, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5D, 0x14, 0x00, 0x00, 0xFC, 0x0D, 0x00, 0x00, + 0xFC, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x05, 0x0E, 0x00, 0x00, 0xDB, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x0E, 0x00, 0x00, + 0xDB, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00, 0xDB, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x61, 0x14, 0x00, 0x00, 0x05, 0x0E, 0x00, 0x00, 0x05, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x64, 0x14, 0x00, 0x00, + 0x07, 0x0E, 0x00, 0x00, 0x07, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x67, 0x14, 0x00, 0x00, 0x09, 0x0E, 0x00, 0x00, + 0x09, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x12, 0x0E, 0x00, 0x00, 0xE2, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x14, 0x0E, 0x00, 0x00, + 0xE2, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0xE2, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6B, 0x14, 0x00, 0x00, 0x12, 0x0E, 0x00, 0x00, 0x12, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6E, 0x14, 0x00, 0x00, + 0x14, 0x0E, 0x00, 0x00, 0x14, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x14, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, + 0x16, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1F, 0x0E, 0x00, 0x00, 0xF7, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x21, 0x0E, 0x00, 0x00, + 0xF7, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x23, 0x0E, 0x00, 0x00, 0xF7, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x75, 0x14, 0x00, 0x00, 0x1F, 0x0E, 0x00, 0x00, 0x1F, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x14, 0x00, 0x00, + 0x21, 0x0E, 0x00, 0x00, 0x21, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7B, 0x14, 0x00, 0x00, 0x23, 0x0E, 0x00, 0x00, + 0x23, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2C, 0x0E, 0x00, 0x00, 0xFE, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x0E, 0x00, 0x00, + 0xFE, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, 0xFE, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7F, 0x14, 0x00, 0x00, 0x2C, 0x0E, 0x00, 0x00, 0x2C, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x82, 0x14, 0x00, 0x00, + 0x2E, 0x0E, 0x00, 0x00, 0x2E, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x85, 0x14, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, + 0x30, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x46, 0x0E, 0x00, 0x00, 0xF0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x48, 0x0E, 0x00, 0x00, + 0xF0, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4A, 0x0E, 0x00, 0x00, 0xF0, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x93, 0x14, 0x00, 0x00, 0x46, 0x0E, 0x00, 0x00, 0x46, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x96, 0x14, 0x00, 0x00, + 0x48, 0x0E, 0x00, 0x00, 0x48, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x99, 0x14, 0x00, 0x00, 0x4A, 0x0E, 0x00, 0x00, + 0x4A, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x53, 0x0E, 0x00, 0x00, 0x05, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x55, 0x0E, 0x00, 0x00, + 0x05, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x57, 0x0E, 0x00, 0x00, 0x05, 0x14, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9D, 0x14, 0x00, 0x00, 0x53, 0x0E, 0x00, 0x00, 0x53, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA0, 0x14, 0x00, 0x00, + 0x55, 0x0E, 0x00, 0x00, 0x55, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA3, 0x14, 0x00, 0x00, 0x57, 0x0E, 0x00, 0x00, + 0x57, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC1, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x3C, 0x14, 0x00, 0x00, 0x46, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC2, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x1E, 0x14, 0x00, 0x00, 0xC1, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC8, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, + 0x6E, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC9, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xC2, 0x14, 0x00, 0x00, 0xC8, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEB, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x3C, 0x14, 0x00, 0x00, 0x46, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEC, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1E, 0x14, 0x00, 0x00, + 0xEB, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF2, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x50, 0x14, 0x00, 0x00, 0x6E, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF3, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xEC, 0x14, 0x00, 0x00, 0xF2, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x46, 0x14, 0x00, 0x00, + 0x50, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x16, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x28, 0x14, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, 0x78, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1D, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x16, 0x15, 0x00, 0x00, + 0x1C, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3F, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x46, 0x14, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x3F, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x46, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, + 0x78, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x47, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x40, 0x15, 0x00, 0x00, 0x46, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x69, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x64, 0x14, 0x00, 0x00, 0x6E, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6A, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x46, 0x14, 0x00, 0x00, + 0x69, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x70, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x78, 0x14, 0x00, 0x00, 0x96, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x6A, 0x15, 0x00, 0x00, 0x70, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x64, 0x14, 0x00, 0x00, + 0x6E, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x94, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x46, 0x14, 0x00, 0x00, 0x93, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9A, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x78, 0x14, 0x00, 0x00, 0x96, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9B, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x94, 0x15, 0x00, 0x00, + 0x9A, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBD, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x6E, 0x14, 0x00, 0x00, 0x78, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBE, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, 0xBD, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC4, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x82, 0x14, 0x00, 0x00, + 0xA0, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC5, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xBE, 0x15, 0x00, 0x00, 0xC4, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE7, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x6E, 0x14, 0x00, 0x00, 0x78, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE8, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, + 0xE7, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEE, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x82, 0x14, 0x00, 0x00, 0xA0, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEF, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE8, 0x15, 0x00, 0x00, 0xEE, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x16, 0x00, 0x00, + 0xF3, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0F, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x0E, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x16, 0x00, 0x00, + 0x0F, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2F, 0x16, 0x00, 0x00, 0x47, 0x15, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x30, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x2F, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x31, 0x16, 0x00, 0x00, 0x30, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x50, 0x16, 0x00, 0x00, 0x9B, 0x15, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x51, 0x16, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x50, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x52, 0x16, 0x00, 0x00, 0x51, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, 0x16, 0x00, 0x00, + 0xEF, 0x15, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x72, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x71, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x16, 0x00, 0x00, + 0x72, 0x16, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAF, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0xF3, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xC9, 0x14, 0x00, 0x00, + 0xAF, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB2, 0x0F, 0x00, 0x00, 0xB0, 0x0F, 0x00, 0x00, 0x10, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9D, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xB2, 0x0F, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC7, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x47, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC8, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x1D, 0x15, 0x00, 0x00, 0xC7, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCA, 0x0F, 0x00, 0x00, 0xC8, 0x0F, 0x00, 0x00, + 0x31, 0x16, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD0, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xCA, 0x0F, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDF, 0x0F, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x9B, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x71, 0x15, 0x00, 0x00, 0xDF, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE2, 0x0F, 0x00, 0x00, + 0xE0, 0x0F, 0x00, 0x00, 0x52, 0x16, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xE2, 0x0F, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF7, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0xEF, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xC5, 0x15, 0x00, 0x00, + 0xF7, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFA, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x73, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x36, 0x17, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xFA, 0x0F, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x64, 0x17, 0x00, 0x00, 0x9D, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x66, 0x17, 0x00, 0x00, + 0x64, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x68, 0x17, 0x00, 0x00, 0x66, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x69, 0x17, 0x00, 0x00, 0x68, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x97, 0x17, 0x00, 0x00, 0xD0, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x99, 0x17, 0x00, 0x00, + 0x97, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9B, 0x17, 0x00, 0x00, 0x99, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9C, 0x17, 0x00, 0x00, 0x9B, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCA, 0x17, 0x00, 0x00, 0x03, 0x17, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCC, 0x17, 0x00, 0x00, + 0xCA, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCE, 0x17, 0x00, 0x00, 0xCC, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCF, 0x17, 0x00, 0x00, 0xCE, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFD, 0x17, 0x00, 0x00, 0x36, 0x17, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0x17, 0x00, 0x00, + 0xFD, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0xFF, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x18, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1E, 0x10, 0x00, 0x00, 0xC7, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, + 0x69, 0x17, 0x00, 0x00, 0x1E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2D, 0x10, 0x00, 0x00, 0x9C, 0x17, 0x00, 0x00, + 0x1E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x36, 0x10, 0x00, 0x00, 0xCF, 0x17, 0x00, 0x00, 0x1E, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x00, + 0x02, 0x18, 0x00, 0x00, 0x1E, 0x10, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, 0x6A, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x46, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, + 0x6A, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4A, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x49, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4B, 0x10, 0x00, 0x00, 0x46, 0x10, 0x00, 0x00, 0x4A, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x52, 0x10, 0x00, 0x00, + 0x45, 0x10, 0x00, 0x00, 0x4A, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x59, 0x10, 0x00, 0x00, 0x46, 0x10, 0x00, 0x00, + 0x49, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5E, 0x10, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x00, + 0xF3, 0x14, 0x00, 0x00, 0xC9, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, + 0x62, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2B, 0x18, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2C, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x2B, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2D, 0x18, 0x00, 0x00, 0x2C, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x66, 0x10, 0x00, 0x00, 0x4B, 0x10, 0x00, 0x00, + 0x2D, 0x18, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6A, 0x10, 0x00, 0x00, 0x47, 0x15, 0x00, 0x00, 0x1D, 0x15, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6B, 0x10, 0x00, 0x00, + 0x0A, 0x08, 0x00, 0x00, 0x6A, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x6B, 0x10, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x18, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0x37, 0x18, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6E, 0x10, 0x00, 0x00, + 0x52, 0x10, 0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x72, 0x10, 0x00, 0x00, 0x9B, 0x15, 0x00, 0x00, + 0x71, 0x15, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x73, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, 0x72, 0x10, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x41, 0x18, 0x00, 0x00, + 0x73, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x42, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x41, 0x18, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x43, 0x18, 0x00, 0x00, + 0x42, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x10, 0x00, 0x00, 0x59, 0x10, 0x00, 0x00, 0x43, 0x18, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7A, 0x10, 0x00, 0x00, + 0xEF, 0x15, 0x00, 0x00, 0xC5, 0x15, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7B, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, + 0x7A, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4C, 0x18, 0x00, 0x00, 0x7B, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4D, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x4C, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4E, 0x18, 0x00, 0x00, 0x4D, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7E, 0x10, 0x00, 0x00, 0x5E, 0x10, 0x00, 0x00, + 0x4E, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x84, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x66, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, + 0x2D, 0x10, 0x00, 0x00, 0x6E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, + 0x76, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA0, 0x10, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA2, 0x10, 0x00, 0x00, + 0xA0, 0x10, 0x00, 0x00, 0x66, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBA, 0x10, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x00, + 0x7E, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBB, 0x10, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, 0xBA, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBD, 0x10, 0x00, 0x00, + 0xBB, 0x10, 0x00, 0x00, 0x6E, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD8, 0x10, 0x00, 0x00, 0xBB, 0x10, 0x00, 0x00, + 0x76, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF3, 0x10, 0x00, 0x00, 0xA0, 0x10, 0x00, 0x00, 0x7E, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6B, 0x1A, 0x00, 0x00, + 0x84, 0x10, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6C, 0x1A, 0x00, 0x00, 0x6B, 0x1A, 0x00, 0x00, + 0x9F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6D, 0x1A, 0x00, 0x00, 0x6C, 0x1A, 0x00, 0x00, 0xBA, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1D, 0x11, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x6D, 0x1A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1F, 0x11, 0x00, 0x00, 0x1D, 0x11, 0x00, 0x00, + 0xA2, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x21, 0x11, 0x00, 0x00, 0x1F, 0x11, 0x00, 0x00, 0xBD, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x23, 0x11, 0x00, 0x00, + 0x21, 0x11, 0x00, 0x00, 0xD8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x25, 0x11, 0x00, 0x00, 0x23, 0x11, 0x00, 0x00, + 0xF3, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x65, 0x18, 0x00, 0x00, 0x25, 0x11, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x66, 0x18, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, + 0x65, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x67, 0x18, 0x00, 0x00, 0x66, 0x18, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x67, 0x18, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6C, 0x18, 0x00, 0x00, + 0x6A, 0x18, 0x00, 0x00, 0x25, 0x11, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6E, 0x18, 0x00, 0x00, 0x6C, 0x18, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6F, 0x18, 0x00, 0x00, 0x67, 0x18, 0x00, 0x00, 0x6E, 0x18, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6E, 0x1A, 0x00, 0x00, + 0x1B, 0x14, 0x00, 0x00, 0x39, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2F, 0x11, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, + 0x6E, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x33, 0x11, 0x00, 0x00, 0x25, 0x14, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x34, 0x11, 0x00, 0x00, + 0x2F, 0x11, 0x00, 0x00, 0x33, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x38, 0x11, 0x00, 0x00, 0x57, 0x14, 0x00, 0x00, + 0x8D, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x39, 0x11, 0x00, 0x00, 0x34, 0x11, 0x00, 0x00, 0x38, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3D, 0x11, 0x00, 0x00, + 0x61, 0x14, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3E, 0x11, 0x00, 0x00, 0x39, 0x11, 0x00, 0x00, + 0x3D, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x42, 0x11, 0x00, 0x00, 0x93, 0x14, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x43, 0x11, 0x00, 0x00, + 0x3E, 0x11, 0x00, 0x00, 0x42, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x7F, 0x14, 0x00, 0x00, + 0xBA, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x48, 0x11, 0x00, 0x00, 0x43, 0x11, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4C, 0x11, 0x00, 0x00, + 0x9D, 0x14, 0x00, 0x00, 0xBA, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4D, 0x11, 0x00, 0x00, 0x48, 0x11, 0x00, 0x00, + 0x4C, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x51, 0x11, 0x00, 0x00, 0x43, 0x14, 0x00, 0x00, 0xA2, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x52, 0x11, 0x00, 0x00, + 0x4D, 0x11, 0x00, 0x00, 0x51, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x56, 0x11, 0x00, 0x00, 0x4D, 0x14, 0x00, 0x00, + 0xBD, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x57, 0x11, 0x00, 0x00, 0x52, 0x11, 0x00, 0x00, 0x56, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5B, 0x11, 0x00, 0x00, + 0x6B, 0x14, 0x00, 0x00, 0xD8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5C, 0x11, 0x00, 0x00, 0x57, 0x11, 0x00, 0x00, + 0x5B, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x60, 0x11, 0x00, 0x00, 0x75, 0x14, 0x00, 0x00, 0xF3, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x61, 0x11, 0x00, 0x00, + 0x5C, 0x11, 0x00, 0x00, 0x60, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x63, 0x11, 0x00, 0x00, 0x61, 0x11, 0x00, 0x00, + 0x6F, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7D, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x63, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6F, 0x1A, 0x00, 0x00, + 0x1E, 0x14, 0x00, 0x00, 0x3C, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6D, 0x11, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, + 0x6F, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x11, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x11, 0x00, 0x00, + 0x6D, 0x11, 0x00, 0x00, 0x71, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x76, 0x11, 0x00, 0x00, 0x5A, 0x14, 0x00, 0x00, + 0x8D, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x77, 0x11, 0x00, 0x00, 0x72, 0x11, 0x00, 0x00, 0x76, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x11, 0x00, 0x00, + 0x64, 0x14, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7C, 0x11, 0x00, 0x00, 0x77, 0x11, 0x00, 0x00, + 0x7B, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x80, 0x11, 0x00, 0x00, 0x96, 0x14, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x81, 0x11, 0x00, 0x00, + 0x7C, 0x11, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x85, 0x11, 0x00, 0x00, 0x82, 0x14, 0x00, 0x00, + 0xBA, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x86, 0x11, 0x00, 0x00, 0x81, 0x11, 0x00, 0x00, 0x85, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8A, 0x11, 0x00, 0x00, + 0xA0, 0x14, 0x00, 0x00, 0xBA, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8B, 0x11, 0x00, 0x00, 0x86, 0x11, 0x00, 0x00, + 0x8A, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8F, 0x11, 0x00, 0x00, 0x46, 0x14, 0x00, 0x00, 0xA2, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x90, 0x11, 0x00, 0x00, + 0x8B, 0x11, 0x00, 0x00, 0x8F, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x94, 0x11, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, + 0xBD, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x95, 0x11, 0x00, 0x00, 0x90, 0x11, 0x00, 0x00, 0x94, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x99, 0x11, 0x00, 0x00, + 0x6E, 0x14, 0x00, 0x00, 0xD8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9A, 0x11, 0x00, 0x00, 0x95, 0x11, 0x00, 0x00, + 0x99, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9E, 0x11, 0x00, 0x00, 0x78, 0x14, 0x00, 0x00, 0xF3, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9F, 0x11, 0x00, 0x00, + 0x9A, 0x11, 0x00, 0x00, 0x9E, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA1, 0x11, 0x00, 0x00, 0x9F, 0x11, 0x00, 0x00, + 0x6F, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8B, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xA1, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x70, 0x1A, 0x00, 0x00, + 0x21, 0x14, 0x00, 0x00, 0x3F, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAB, 0x11, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, + 0x70, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAF, 0x11, 0x00, 0x00, 0x2B, 0x14, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x11, 0x00, 0x00, + 0xAB, 0x11, 0x00, 0x00, 0xAF, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB4, 0x11, 0x00, 0x00, 0x5D, 0x14, 0x00, 0x00, + 0x8D, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB5, 0x11, 0x00, 0x00, 0xB0, 0x11, 0x00, 0x00, 0xB4, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB9, 0x11, 0x00, 0x00, + 0x67, 0x14, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBA, 0x11, 0x00, 0x00, 0xB5, 0x11, 0x00, 0x00, + 0xB9, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBE, 0x11, 0x00, 0x00, 0x99, 0x14, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBF, 0x11, 0x00, 0x00, + 0xBA, 0x11, 0x00, 0x00, 0xBE, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC3, 0x11, 0x00, 0x00, 0x85, 0x14, 0x00, 0x00, + 0xBA, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC4, 0x11, 0x00, 0x00, 0xBF, 0x11, 0x00, 0x00, 0xC3, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC8, 0x11, 0x00, 0x00, + 0xA3, 0x14, 0x00, 0x00, 0xBA, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC9, 0x11, 0x00, 0x00, 0xC4, 0x11, 0x00, 0x00, + 0xC8, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCD, 0x11, 0x00, 0x00, 0x49, 0x14, 0x00, 0x00, 0xA2, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCE, 0x11, 0x00, 0x00, + 0xC9, 0x11, 0x00, 0x00, 0xCD, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD2, 0x11, 0x00, 0x00, 0x53, 0x14, 0x00, 0x00, + 0xBD, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD3, 0x11, 0x00, 0x00, 0xCE, 0x11, 0x00, 0x00, 0xD2, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD7, 0x11, 0x00, 0x00, + 0x71, 0x14, 0x00, 0x00, 0xD8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD8, 0x11, 0x00, 0x00, 0xD3, 0x11, 0x00, 0x00, + 0xD7, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDC, 0x11, 0x00, 0x00, 0x7B, 0x14, 0x00, 0x00, 0xF3, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDD, 0x11, 0x00, 0x00, + 0xD8, 0x11, 0x00, 0x00, 0xDC, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDF, 0x11, 0x00, 0x00, 0xDD, 0x11, 0x00, 0x00, + 0x6F, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x99, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xDF, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xDE, 0x09, 0x00, 0x00, 0xDF, 0x09, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xDF, 0x09, 0x00, 0x00, 0x7D, 0x18, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xDE, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, + 0x52, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x8B, 0x18, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xDE, 0x09, 0x00, 0x00, + 0xE3, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xE3, 0x09, 0x00, 0x00, 0x99, 0x18, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xE5, 0x09, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0xE6, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xE5, 0x09, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE8, 0x09, 0x00, 0x00, + 0xE6, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xDF, 0x09, 0x00, 0x00, 0xE8, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEA, 0x09, 0x00, 0x00, 0xE6, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0xEA, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEC, 0x09, 0x00, 0x00, 0xE6, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xE3, 0x09, 0x00, 0x00, 0xEC, 0x09, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xED, 0x09, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xEE, 0x09, 0x00, 0x00, 0xED, 0x09, 0x00, 0x00, 0xED, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xA5, 0x18, 0x00, 0x00, + 0xBF, 0x09, 0x00, 0x00, 0x7A, 0x1A, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA7, 0x18, 0x00, 0x00, 0xA5, 0x18, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA8, 0x18, 0x00, 0x00, 0xA7, 0x18, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAA, 0x18, 0x00, 0x00, + 0xA5, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAB, 0x18, 0x00, 0x00, 0xA8, 0x18, 0x00, 0x00, + 0xAA, 0x18, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xA0, 0x18, 0x00, 0x00, + 0x51, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0xAC, 0x18, 0x00, 0x00, 0xA0, 0x18, 0x00, 0x00, 0xAB, 0x18, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAD, 0x18, 0x00, 0x00, + 0xAC, 0x18, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xF2, 0x09, 0x00, 0x00, 0xAD, 0x18, 0x00, 0x00, 0xAD, 0x18, 0x00, 0x00, + 0xAD, 0x18, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xF3, 0x09, 0x00, 0x00, 0xEE, 0x09, 0x00, 0x00, 0xF2, 0x09, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xF3, 0x09, 0x00, 0x00, + 0xF4, 0x09, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x09, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xDF, 0x09, 0x00, 0x00, + 0xF8, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFA, 0x09, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xE1, 0x09, 0x00, 0x00, 0xFA, 0x09, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFC, 0x09, 0x00, 0x00, + 0xF6, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xE3, 0x09, 0x00, 0x00, 0xFC, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xDE, 0x09, 0x00, 0x00, 0xFE, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, + 0xFD, 0x09, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xFE, 0x09, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.spv new file mode 100644 index 000000000..9f2180d61 Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.txt new file mode 100644 index 000000000..b98aa1de1 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.txt @@ -0,0 +1,719 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 6779 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeCasSharpenConstants "XeCasSharpenConstants" + OpMemberName %XeCasSharpenConstants 0 "xe_cas_output_offset" + OpMemberName %XeCasSharpenConstants 1 "xe_cas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeCasSharpenConstants 0 Offset 16 + OpMemberDecorate %XeCasSharpenConstants 1 Offset 24 + OpDecorate %XeCasSharpenConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %float = OpTypeFloat 32 +%_ptr_Function_float = OpTypePointer Function %float + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v3float = OpTypeVector %float 3 + %uint_15 = OpConstant %uint 15 + %uint_256 = OpConstant %uint 256 +%_arr_float_uint_256 = OpTypeArray %float %uint_256 +%float_n0_00100337015 = OpConstant %float -0.00100337015 +%float_0_000880821084 = OpConstant %float 0.000880821084 +%float_0_00169270835 = OpConstant %float 0.00169270835 +%float_n0_00155484071 = OpConstant %float -0.00155484071 +%float_0_00127910543 = OpConstant %float 0.00127910543 +%float_n0_000605085806 = OpConstant %float -0.000605085806 +%float_0_00106464466 = OpConstant %float 0.00106464466 +%float_n0_00138633582 = OpConstant %float -0.00138633582 +%float_0_00135569857 = OpConstant %float 0.00135569857 +%float_0_000513174047 = OpConstant %float 0.000513174047 +%float_0_00121783093 = OpConstant %float 0.00121783093 +%float_n0_00160079659 = OpConstant %float -0.00160079659 +%float_0_00058976718 = OpConstant %float 0.00058976718 +%float_n0_00028339462 = OpConstant %float -0.00028339462 +%float_0_00111060054 = OpConstant %float 0.00111060054 +%float_n0_00141697307 = OpConstant %float -0.00141697307 +%float_0_00144761032 = OpConstant %float 0.00144761032 +%float_n0_0005438113 = OpConstant %float -0.0005438113 +%float_0_00013020834 = OpConstant %float 0.00013020834 +%float_n0_0012025123 = OpConstant %float -0.0012025123 +%float_0_000436580885 = OpConstant %float 0.000436580885 +%float_n0_00104932603 = OpConstant %float -0.00104932603 +%float_0_000620404433 = OpConstant %float 0.000620404433 +%float_n0_000482536765 = OpConstant %float -0.000482536765 +%float_0_00187653187 = OpConstant %float 0.00187653187 +%float_n0_00109528191 = OpConstant %float -0.00109528191 +%float_n9_95710798en05 = OpConstant %float -9.95710798e-05 +%float_n0_000528492674 = OpConstant %float -0.000528492674 +%float_0_0014322917 = OpConstant %float 0.0014322917 +%float_n0_00193780637 = OpConstant %float -0.00193780637 +%float_n0_000696997566 = OpConstant %float -0.000696997566 +%float_3_829657en05 = OpConstant %float 3.829657e-05 +%float_0_000712316192 = OpConstant %float 0.000712316192 +%float_n0_00130974269 = OpConstant %float -0.00130974269 +%float_0_00109528191 = OpConstant %float 0.00109528191 +%float_n0_000298713247 = OpConstant %float -0.000298713247 +%float_0_00175398286 = OpConstant %float 0.00175398286 +%float_n0_00167738972 = OpConstant %float -0.00167738972 +%float_0_00147824758 = OpConstant %float 0.00147824758 +%float_n3_829657en05 = OpConstant %float -3.829657e-05 +%float_0_000788909325 = OpConstant %float 0.000788909325 +%float_n0_00183057599 = OpConstant %float -0.00183057599 +%float_0_000298713247 = OpConstant %float 0.000298713247 +%float_0_000988051528 = OpConstant %float 0.000988051528 +%float_n0_00117187505 = OpConstant %float -0.00117187505 +%float_0_00017616422 = OpConstant %float 0.00017616422 +%float_0_00164675247 = OpConstant %float 0.00164675247 +%float_n0_00158547796 = OpConstant %float -0.00158547796 +%float_0_000344669126 = OpConstant %float 0.000344669126 +%float_0_00186121324 = OpConstant %float 0.00186121324 +%float_n0_00176930148 = OpConstant %float -0.00176930148 +%float_n0_000865502458 = OpConstant %float -0.000865502458 +%float_0_000896139711 = OpConstant %float 0.000896139711 +%float_0_000160845593 = OpConstant %float 0.000160845593 +%float_n0_000926776964 = OpConstant %float -0.000926776964 +%float_n0_00152420346 = OpConstant %float -0.00152420346 +%float_n0_000651041686 = OpConstant %float -0.000651041686 +%float_0_00129442406 = OpConstant %float 0.00129442406 +%float_n0_000804227951 = OpConstant %float -0.000804227951 +%float_n0_00146292895 = OpConstant %float -0.00146292895 +%float_0_00179993873 = OpConstant %float 0.00179993873 +%float_n0_000850183831 = OpConstant %float -0.000850183831 +%float_0_000850183831 = OpConstant %float 0.000850183831 +%float_n0_000451899512 = OpConstant %float -0.000451899512 +%float_n0_00106464466 = OpConstant %float -0.00106464466 +%float_n0_000145526967 = OpConstant %float -0.000145526967 +%float_0_000237438726 = OpConstant %float 0.000237438726 +%float_0_00141697307 = OpConstant %float 0.00141697307 +%float_n0_00058976718 = OpConstant %float -0.00058976718 +%float_n0_000191482846 = OpConstant %float -0.000191482846 +%float_0_00160079659 = OpConstant %float 0.00160079659 +%float_0_00101868878 = OpConstant %float 0.00101868878 +%float_0_000405943632 = OpConstant %float 0.000405943632 +%float_n0_000206801473 = OpConstant %float -0.000206801473 +%float_0_00158547796 = OpConstant %float 0.00158547796 +%float_0_000651041686 = OpConstant %float 0.000651041686 +%float_n6_89338267en05 = OpConstant %float -6.89338267e-05 +%float_0_000421262259 = OpConstant %float 0.000421262259 +%float_n0_00164675247 = OpConstant %float -0.00164675247 +%float_0_00137101719 = OpConstant %float 0.00137101719 +%float_0_000926776964 = OpConstant %float 0.000926776964 +%float_n0_000666360313 = OpConstant %float -0.000666360313 +%float_0_00118719367 = OpConstant %float 0.00118719367 +%float_n0_00144761032 = OpConstant %float -0.00144761032 +%float_0_000574448553 = OpConstant %float 0.000574448553 +%float_n0_00189185049 = OpConstant %float -0.00189185049 +%float_0_000758272072 = OpConstant %float 0.000758272072 +%float_n0_00129442406 = OpConstant %float -0.00129442406 +%float_0_00192248775 = OpConstant %float 0.00192248775 +%float_n0_0016620711 = OpConstant %float -0.0016620711 +%float_n0_00103400741 = OpConstant %float -0.00103400741 +%float_n0_000497855421 = OpConstant %float -0.000497855421 +%float_n0_00186121324 = OpConstant %float -0.00186121324 +%float_0_0012025123 = OpConstant %float 0.0012025123 +%float_n0_0003293505 = OpConstant %float -0.0003293505 +%float_n0_00137101719 = OpConstant %float -0.00137101719 +%float_0_00163143384 = OpConstant %float 0.00163143384 +%float_n0_00184589461 = OpConstant %float -0.00184589461 +%float_0_000727634819 = OpConstant %float 0.000727634819 +%float_n0_000911458337 = OpConstant %float -0.000911458337 +%float_0_00181525736 = OpConstant %float 0.00181525736 +%float_n0_00114123779 = OpConstant %float -0.00114123779 +%float_n0_000375306379 = OpConstant %float -0.000375306379 +%float_9_95710798en05 = OpConstant %float 9.95710798e-05 +%float_n0_000742953445 = OpConstant %float -0.000742953445 +%float_0_00117187505 = OpConstant %float 0.00117187505 +%float_6_89338267en05 = OpConstant %float 6.89338267e-05 +%float_0_0014935662 = OpConstant %float 0.0014935662 +%float_0_000972732843 = OpConstant %float 0.000972732843 +%float_n0_000957414217 = OpConstant %float -0.000957414217 +%float_0_00193780637 = OpConstant %float 0.00193780637 +%float_0_000528492674 = OpConstant %float 0.000528492674 +%float_5_36151965en05 = OpConstant %float 5.36151965e-05 +%float_n0_00124846818 = OpConstant %float -0.00124846818 +%float_n0_000268075994 = OpConstant %float -0.000268075994 +%float_0_00153952208 = OpConstant %float 0.00153952208 +%float_n7_65931418en06 = OpConstant %float -7.65931418e-06 +%float_0_000314031873 = OpConstant %float 0.000314031873 +%float_0_00134037994 = OpConstant %float 0.00134037994 +%float_n0_00175398286 = OpConstant %float -0.00175398286 +%float_0_000497855421 = OpConstant %float 0.000497855421 +%float_n0_00118719367 = OpConstant %float -0.00118719367 +%float_0_000773590698 = OpConstant %float 0.000773590698 +%float_n0_00134037994 = OpConstant %float -0.00134037994 +%float_0_000268075994 = OpConstant %float 0.000268075994 +%float_n0_00147824758 = OpConstant %float -0.00147824758 +%float_n0_00013020834 = OpConstant %float -0.00013020834 +%float_n0_000773590698 = OpConstant %float -0.000773590698 +%float_0_00130974269 = OpConstant %float 0.00130974269 +%float_0_000390625006 = OpConstant %float 0.000390625006 +%float_0_000957414217 = OpConstant %float 0.000957414217 +%float_n0_000467218139 = OpConstant %float -0.000467218139 +%float_n0_00153952208 = OpConstant %float -0.00153952208 +%float_0_00103400741 = OpConstant %float 0.00103400741 +%float_n0_000681678939 = OpConstant %float -0.000681678939 +%float_0_00167738972 = OpConstant %float 0.00167738972 +%float_0_00100337015 = OpConstant %float 0.00100337015 +%float_n0_000421262259 = OpConstant %float -0.000421262259 +%float_0_00178462011 = OpConstant %float 0.00178462011 +%float_n0_000237438726 = OpConstant %float -0.000237438726 +%float_n0_000620404433 = OpConstant %float -0.000620404433 +%float_0_0016620711 = OpConstant %float 0.0016620711 +%float_0_000834865205 = OpConstant %float 0.000834865205 +%float_n0_0017233456 = OpConstant %float -0.0017233456 +%float_n0_00107996329 = OpConstant %float -0.00107996329 +%float_0_00176930148 = OpConstant %float 0.00176930148 +%float_n0_000788909325 = OpConstant %float -0.000788909325 +%float_n0_00178462011 = OpConstant %float -0.00178462011 +%float_0_000681678939 = OpConstant %float 0.000681678939 +%float_n0_000988051528 = OpConstant %float -0.000988051528 +%float_n0_00132506131 = OpConstant %float -0.00132506131 +%float_n0_00017616422 = OpConstant %float -0.00017616422 +%float_n0_00150888483 = OpConstant %float -0.00150888483 +%float_0_0003293505 = OpConstant %float 0.0003293505 +%float_n0_001953125 = OpConstant %float -0.001953125 +%float_0_000666360313 = OpConstant %float 0.000666360313 +%float_n0_00161611522 = OpConstant %float -0.00161611522 +%float_0_00115655642 = OpConstant %float 0.00115655642 +%float_0_000451899512 = OpConstant %float 0.000451899512 +%float_n0_000436580885 = OpConstant %float -0.000436580885 +%float_0_000191482846 = OpConstant %float 0.000191482846 +%float_n0_0014935662 = OpConstant %float -0.0014935662 +%float_0_00114123779 = OpConstant %float 0.00114123779 +%float_8_42524532en05 = OpConstant %float 8.42524532e-05 +%float_0_00189185049 = OpConstant %float 0.00189185049 +%float_0_00140165444 = OpConstant %float 0.00140165444 +%float_0_000559129927 = OpConstant %float 0.000559129927 +%float_0_000114889706 = OpConstant %float 0.000114889706 +%float_0_00126378681 = OpConstant %float 0.00126378681 +%float_n0_000574448553 = OpConstant %float -0.000574448553 +%float_n0_000972732843 = OpConstant %float -0.000972732843 +%float_0_00132506131 = OpConstant %float 0.00132506131 +%float_0_000222120099 = OpConstant %float 0.000222120099 +%float_n0_000758272072 = OpConstant %float -0.000758272072 +%float_n0_00135569857 = OpConstant %float -0.00135569857 +%float_0_00146292895 = OpConstant %float 0.00146292895 +%float_0_000865502458 = OpConstant %float 0.000865502458 +%float_n0_000359987753 = OpConstant %float -0.000359987753 +%float_0_0005438113 = OpConstant %float 0.0005438113 +%float_n0_00112591917 = OpConstant %float -0.00112591917 +%float_n0_000252757367 = OpConstant %float -0.000252757367 +%float_n0_000559129927 = OpConstant %float -0.000559129927 +%float_n0_00181525736 = OpConstant %float -0.00181525736 +%float_0_0017233456 = OpConstant %float 0.0017233456 +%float_n0_00115655642 = OpConstant %float -0.00115655642 +%float_0_000742953445 = OpConstant %float 0.000742953445 +%float_0_00157015934 = OpConstant %float 0.00157015934 +%float_n0_000114889706 = OpConstant %float -0.000114889706 +%float_n0_00121783093 = OpConstant %float -0.00121783093 +%float_0_00183057599 = OpConstant %float 0.00183057599 +%float_2_29779416en05 = OpConstant %float 2.29779416e-05 +%float_n0_00192248775 = OpConstant %float -0.00192248775 +%float_0_00173866423 = OpConstant %float 0.00173866423 +%float_n0_000712316192 = OpConstant %float -0.000712316192 +%float_0_00155484071 = OpConstant %float 0.00155484071 +%float_n0_00170802698 = OpConstant %float -0.00170802698 +%float_0_00123314955 = OpConstant %float 0.00123314955 +%float_0_000206801473 = OpConstant %float 0.000206801473 +%float_0_00104932603 = OpConstant %float 0.00104932603 +%float_n0_000727634819 = OpConstant %float -0.000727634819 +%float_n0_00163143384 = OpConstant %float -0.00163143384 +%float_n0_000314031873 = OpConstant %float -0.000314031873 +%float_0_000482536765 = OpConstant %float 0.000482536765 +%float_n0_00179993873 = OpConstant %float -0.00179993873 +%float_0_00094209559 = OpConstant %float 0.00094209559 +%float_n0_000344669126 = OpConstant %float -0.000344669126 +%float_0_000696997566 = OpConstant %float 0.000696997566 +%float_n0_00101868878 = OpConstant %float -0.00101868878 +%float_n0_00157015934 = OpConstant %float -0.00157015934 +%float_n2_29779416en05 = OpConstant %float -2.29779416e-05 +%float_n0_00127910543 = OpConstant %float -0.00127910543 +%float_0_000804227951 = OpConstant %float 0.000804227951 +%float_n0_000896139711 = OpConstant %float -0.000896139711 +%float_n0_0014322917 = OpConstant %float -0.0014322917 +%float_0_000605085806 = OpConstant %float 0.000605085806 +%float_n8_42524532en05 = OpConstant %float -8.42524532e-05 +%float_0_000911458337 = OpConstant %float 0.000911458337 +%float_0_001953125 = OpConstant %float 0.001953125 +%float_n0_00140165444 = OpConstant %float -0.00140165444 +%float_n0_00063572306 = OpConstant %float -0.00063572306 +%float_0_00150888483 = OpConstant %float 0.00150888483 +%float_n0_000819546578 = OpConstant %float -0.000819546578 +%float_0_00124846818 = OpConstant %float 0.00124846818 +%float_0_000252757367 = OpConstant %float 0.000252757367 +%float_0_00152420346 = OpConstant %float 0.00152420346 +%float_0_00112591917 = OpConstant %float 0.00112591917 +%float_0_000359987753 = OpConstant %float 0.000359987753 +%float_n0_000390625006 = OpConstant %float -0.000390625006 +%float_0_00190716912 = OpConstant %float 0.00190716912 +%float_0_00138633582 = OpConstant %float 0.00138633582 +%float_n0_00111060054 = OpConstant %float -0.00111060054 +%float_0_00161611522 = OpConstant %float 0.00161611522 +%float_n0_000880821084 = OpConstant %float -0.000880821084 +%float_0_000145526967 = OpConstant %float 0.000145526967 +%float_0_00107996329 = OpConstant %float 0.00107996329 +%float_n5_36151965en05 = OpConstant %float -5.36151965e-05 +%float_0_00028339462 = OpConstant %float 0.00028339462 +%float_n0_00169270835 = OpConstant %float -0.00169270835 +%float_n0_00126378681 = OpConstant %float -0.00126378681 +%float_n0_000513174047 = OpConstant %float -0.000513174047 +%float_n0_000160845593 = OpConstant %float -0.000160845593 +%float_n0_00187653187 = OpConstant %float -0.00187653187 +%float_n0_000834865205 = OpConstant %float -0.000834865205 +%float_0_00063572306 = OpConstant %float 0.00063572306 +%float_7_65931418en06 = OpConstant %float 7.65931418e-06 +%float_n0_00190716912 = OpConstant %float -0.00190716912 +%float_n0_000222120099 = OpConstant %float -0.000222120099 +%float_0_000375306379 = OpConstant %float 0.000375306379 +%float_n0_00173866423 = OpConstant %float -0.00173866423 +%float_n0_000405943632 = OpConstant %float -0.000405943632 +%float_n0_00123314955 = OpConstant %float -0.00123314955 +%float_0_00170802698 = OpConstant %float 0.00170802698 +%float_n0_00094209559 = OpConstant %float -0.00094209559 +%float_0_000819546578 = OpConstant %float 0.000819546578 +%float_0_00184589461 = OpConstant %float 0.00184589461 +%float_0_000467218139 = OpConstant %float 0.000467218139 + %337 = OpConstantComposite %_arr_float_uint_256 %float_n0_00100337015 %float_0_000880821084 %float_0_00169270835 %float_n0_00155484071 %float_0_00127910543 %float_n0_000605085806 %float_0_00106464466 %float_n0_00138633582 %float_0_00135569857 %float_0_000513174047 %float_0_00121783093 %float_n0_00160079659 %float_0_00058976718 %float_n0_00028339462 %float_0_00111060054 %float_n0_00141697307 %float_0_00144761032 %float_n0_0005438113 %float_0_00013020834 %float_n0_0012025123 %float_0_000436580885 %float_n0_00104932603 %float_0_000620404433 %float_n0_000482536765 %float_0_00187653187 %float_n0_00109528191 %float_n9_95710798en05 %float_n0_000528492674 %float_0_0014322917 %float_n0_00193780637 %float_n0_000696997566 %float_3_829657en05 %float_0_000712316192 %float_n0_00130974269 %float_0_00109528191 %float_n0_000298713247 %float_0_00175398286 %float_n0_00167738972 %float_0_00147824758 %float_n3_829657en05 %float_0_000788909325 %float_n0_00183057599 %float_0_000298713247 %float_0_000988051528 %float_n0_00117187505 %float_0_00017616422 %float_0_00164675247 %float_n0_00158547796 %float_0_000344669126 %float_0_00186121324 %float_n0_00176930148 %float_n0_000865502458 %float_0_000896139711 %float_0_000160845593 %float_n0_000926776964 %float_n0_00152420346 %float_n0_000651041686 %float_0_00129442406 %float_n0_000804227951 %float_n0_00146292895 %float_0_00179993873 %float_n0_000850183831 %float_0_000850183831 %float_n0_000451899512 %float_n0_00106464466 %float_n0_000145526967 %float_0_000237438726 %float_0_00141697307 %float_n0_00058976718 %float_n0_000191482846 %float_0_00160079659 %float_0_00101868878 %float_0_000405943632 %float_n0_000206801473 %float_0_00158547796 %float_0_000651041686 %float_n6_89338267en05 %float_0_000421262259 %float_n0_00164675247 %float_0_00137101719 %float_0_000926776964 %float_n0_000666360313 %float_0_00118719367 %float_n0_00144761032 %float_0_000574448553 %float_n0_00189185049 %float_0_000758272072 %float_n0_00129442406 %float_0_00192248775 %float_n0_0016620711 %float_n0_00103400741 %float_n0_000497855421 %float_n0_00186121324 %float_0_0012025123 %float_n0_0003293505 %float_n0_00137101719 %float_0_00163143384 %float_n0_00184589461 %float_0_000727634819 %float_n0_000911458337 %float_0_00181525736 %float_n0_00114123779 %float_n0_000375306379 %float_9_95710798en05 %float_n0_000742953445 %float_0_00117187505 %float_6_89338267en05 %float_0_0014935662 %float_0_000972732843 %float_n0_000957414217 %float_0_00193780637 %float_0_000528492674 %float_5_36151965en05 %float_n0_00124846818 %float_n0_000268075994 %float_0_00153952208 %float_n7_65931418en06 %float_0_000314031873 %float_0_00134037994 %float_n0_00175398286 %float_0_000497855421 %float_n0_00118719367 %float_0_000773590698 %float_n0_00134037994 %float_0_000268075994 %float_n0_00147824758 %float_n0_00013020834 %float_n0_000773590698 %float_0_00130974269 %float_0_000390625006 %float_0_000957414217 %float_n0_000467218139 %float_n0_00153952208 %float_0_00103400741 %float_n0_000681678939 %float_0_00167738972 %float_0_00100337015 %float_n0_000421262259 %float_0_00178462011 %float_n0_000237438726 %float_n0_000620404433 %float_0_0016620711 %float_0_000834865205 %float_n0_0017233456 %float_n0_00107996329 %float_0_00176930148 %float_n0_000788909325 %float_n0_00178462011 %float_0_000681678939 %float_n0_000988051528 %float_n0_00132506131 %float_n0_00017616422 %float_n0_00150888483 %float_0_0003293505 %float_n0_001953125 %float_0_000666360313 %float_n0_00161611522 %float_0_00115655642 %float_0_000451899512 %float_n0_000436580885 %float_0_000191482846 %float_n0_0014935662 %float_0_00114123779 %float_8_42524532en05 %float_0_00189185049 %float_0_00140165444 %float_0_000559129927 %float_0_000114889706 %float_0_00126378681 %float_n0_000574448553 %float_n0_000972732843 %float_0_00132506131 %float_0_000222120099 %float_n0_000758272072 %float_n0_00135569857 %float_0_00146292895 %float_0_000865502458 %float_n0_000359987753 %float_0_0005438113 %float_n0_00112591917 %float_n0_000252757367 %float_n0_000559129927 %float_n0_00181525736 %float_0_0017233456 %float_n0_00115655642 %float_0_000742953445 %float_0_00157015934 %float_n0_000114889706 %float_n0_00121783093 %float_0_00183057599 %float_2_29779416en05 %float_n0_00192248775 %float_0_00173866423 %float_n0_000712316192 %float_0_00155484071 %float_n0_00170802698 %float_0_00123314955 %float_0_000206801473 %float_0_00104932603 %float_n0_000727634819 %float_n0_00163143384 %float_n0_000314031873 %float_0_000482536765 %float_n0_00179993873 %float_0_00094209559 %float_n0_000344669126 %float_0_000696997566 %float_n0_00101868878 %float_n0_00157015934 %float_n2_29779416en05 %float_n0_00127910543 %float_0_000804227951 %float_n0_000896139711 %float_n0_0014322917 %float_0_000605085806 %float_n8_42524532en05 %float_0_000911458337 %float_0_001953125 %float_n0_00140165444 %float_n0_00063572306 %float_0_00150888483 %float_n0_000819546578 %float_0_00124846818 %float_0_000252757367 %float_0_00152420346 %float_0_00112591917 %float_0_000359987753 %float_n0_000390625006 %float_0_00190716912 %float_0_00138633582 %float_n0_00111060054 %float_0_00161611522 %float_n0_000880821084 %float_0_000145526967 %float_0_00107996329 %float_n5_36151965en05 %float_0_00028339462 %float_n0_00169270835 %float_n0_00126378681 %float_n0_000513174047 %float_n0_000160845593 %float_n0_00187653187 %float_n0_000834865205 %float_0_00063572306 %float_7_65931418en06 %float_n0_00190716912 %float_n0_000222120099 %float_0_000375306379 %float_n0_00173866423 %float_n0_000405943632 %float_n0_00123314955 %float_0_00170802698 %float_n0_00094209559 %float_0_000819546578 %float_0_00184589461 %float_0_000467218139 + %uint_1 = OpConstant %uint 1 + %uint_16 = OpConstant %uint 16 + %uint_0 = OpConstant %uint 0 +%_ptr_Function__arr_float_uint_256 = OpTypePointer Function %_arr_float_uint_256 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 +%uint_532432441 = OpConstant %uint 532432441 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %424 = OpTypeImage %float 2D 0 0 0 1 Unknown + %425 = OpTypeSampledImage %424 +%_ptr_UniformConstant_425 = OpTypePointer UniformConstant %425 + %xe_texture = OpVariable %_ptr_UniformConstant_425 UniformConstant + %int_0 = OpConstant %int 0 + %v4float = OpTypeVector %float 4 + %int_n1 = OpConstant %int -1 + %462 = OpConstantComposite %v2int %int_0 %int_n1 + %int_1 = OpConstant %int 1 + %469 = OpConstantComposite %v2int %int_1 %int_n1 + %475 = OpConstantComposite %v2int %int_n1 %int_0 + %485 = OpConstantComposite %v2int %int_1 %int_0 + %491 = OpConstantComposite %v2int %int_n1 %int_1 + %497 = OpConstantComposite %v2int %int_0 %int_1 + %503 = OpConstantComposite %v2int %int_1 %int_1 + %uint_2 = OpConstant %uint 2 + %v2float = OpTypeVector %float 2 + %int_2 = OpConstant %int 2 + %992 = OpConstantComposite %v2int %int_2 %int_0 + %1014 = OpConstantComposite %v2int %int_0 %int_2 + %1025 = OpConstantComposite %v2int %int_2 %int_1 + %1031 = OpConstantComposite %v2int %int_1 %int_2 +%float_0_03125 = OpConstant %float 0.03125 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeCasSharpenConstants = OpTypeStruct %v2int %float +%_ptr_PushConstant_XeCasSharpenConstants = OpTypePointer PushConstant %XeCasSharpenConstants + %_ = OpVariable %_ptr_PushConstant_XeCasSharpenConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %2548 = OpConstantComposite %v3float %float_0 %float_0 %float_0 + %2549 = OpConstantComposite %v3float %float_1 %float_1 %float_1 + %uint_3 = OpConstant %uint 3 + %6778 = OpConstantComposite %v2uint %uint_15 %uint_15 + %main = OpFunction %void None %3 + %5 = OpLabel + %6304 = OpVariable %_ptr_Function__arr_float_uint_256 Function + %2485 = OpLoad %v4float %gl_FragCoord + %2486 = OpVectorShuffle %v2float %2485 %2485 0 1 + %2487 = OpConvertFToS %v2int %2486 + %2492 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %2493 = OpLoad %v2int %2492 + %2494 = OpISub %v2int %2487 %2493 + %2495 = OpBitcast %v2uint %2494 + %2501 = OpAccessChain %_ptr_PushConstant_float %_ %int_1 + %2502 = OpLoad %float %2501 + %2503 = OpBitcast %uint %2502 + OpBranch %3064 + %3064 = OpLabel + %3415 = OpConvertUToF %v2float %2495 + %3431 = OpExtInst %v2float %1 Floor %3415 + %3434 = OpFSub %v2float %3415 %3431 + %3436 = OpConvertFToS %v2int %3431 + %3441 = OpIAdd %v2int %3436 %462 + %5031 = OpLoad %425 %xe_texture + %5033 = OpImage %424 %5031 + %5034 = OpImageFetch %v4float %5033 %3441 Lod %int_0 + %3444 = OpIAdd %v2int %3436 %475 + %5040 = OpImage %424 %5031 + %5041 = OpImageFetch %v4float %5040 %3444 Lod %int_0 + %5047 = OpImage %424 %5031 + %5048 = OpImageFetch %v4float %5047 %3436 Lod %int_0 + %3449 = OpIAdd %v2int %3436 %469 + %5054 = OpImage %424 %5031 + %5055 = OpImageFetch %v4float %5054 %3449 Lod %int_0 + %3455 = OpIAdd %v2int %3436 %485 + %5068 = OpImage %424 %5031 + %5069 = OpImageFetch %v4float %5068 %3455 Lod %int_0 + %3458 = OpIAdd %v2int %3436 %992 + %5075 = OpImage %424 %5031 + %5076 = OpImageFetch %v4float %5075 %3458 Lod %int_0 + %3461 = OpIAdd %v2int %3436 %491 + %5082 = OpImage %424 %5031 + %5083 = OpImageFetch %v4float %5082 %3461 Lod %int_0 + %3464 = OpIAdd %v2int %3436 %497 + %5089 = OpImage %424 %5031 + %5090 = OpImageFetch %v4float %5089 %3464 Lod %int_0 + %3470 = OpIAdd %v2int %3436 %1014 + %5103 = OpImage %424 %5031 + %5104 = OpImageFetch %v4float %5103 %3470 Lod %int_0 + %3473 = OpIAdd %v2int %3436 %503 + %5110 = OpImage %424 %5031 + %5111 = OpImageFetch %v4float %5110 %3473 Lod %int_0 + %3476 = OpIAdd %v2int %3436 %1025 + %5117 = OpImage %424 %5031 + %5118 = OpImageFetch %v4float %5117 %3476 Lod %int_0 + %3479 = OpIAdd %v2int %3436 %1031 + %5124 = OpImage %424 %5031 + %5125 = OpImageFetch %v4float %5124 %3479 Lod %int_0 + %3498 = OpCompositeExtract %float %5034 0 + %3500 = OpCompositeExtract %float %5034 1 + %3502 = OpCompositeExtract %float %5034 2 + %5147 = OpFMul %float %3498 %3498 + %5150 = OpFMul %float %3500 %3500 + %5153 = OpFMul %float %3502 %3502 + %3511 = OpCompositeExtract %float %5055 0 + %3513 = OpCompositeExtract %float %5055 1 + %3515 = OpCompositeExtract %float %5055 2 + %5157 = OpFMul %float %3511 %3511 + %5160 = OpFMul %float %3513 %3513 + %5163 = OpFMul %float %3515 %3515 + %3537 = OpCompositeExtract %float %5041 0 + %3539 = OpCompositeExtract %float %5041 1 + %3541 = OpCompositeExtract %float %5041 2 + %5177 = OpFMul %float %3537 %3537 + %5180 = OpFMul %float %3539 %3539 + %5183 = OpFMul %float %3541 %3541 + %3550 = OpCompositeExtract %float %5048 0 + %3552 = OpCompositeExtract %float %5048 1 + %3554 = OpCompositeExtract %float %5048 2 + %5187 = OpFMul %float %3550 %3550 + %5190 = OpFMul %float %3552 %3552 + %5193 = OpFMul %float %3554 %3554 + %3563 = OpCompositeExtract %float %5069 0 + %3565 = OpCompositeExtract %float %5069 1 + %3567 = OpCompositeExtract %float %5069 2 + %5197 = OpFMul %float %3563 %3563 + %5200 = OpFMul %float %3565 %3565 + %5203 = OpFMul %float %3567 %3567 + %3576 = OpCompositeExtract %float %5076 0 + %3578 = OpCompositeExtract %float %5076 1 + %3580 = OpCompositeExtract %float %5076 2 + %5207 = OpFMul %float %3576 %3576 + %5210 = OpFMul %float %3578 %3578 + %5213 = OpFMul %float %3580 %3580 + %3589 = OpCompositeExtract %float %5083 0 + %3591 = OpCompositeExtract %float %5083 1 + %3593 = OpCompositeExtract %float %5083 2 + %5217 = OpFMul %float %3589 %3589 + %5220 = OpFMul %float %3591 %3591 + %5223 = OpFMul %float %3593 %3593 + %3602 = OpCompositeExtract %float %5090 0 + %3604 = OpCompositeExtract %float %5090 1 + %3606 = OpCompositeExtract %float %5090 2 + %5227 = OpFMul %float %3602 %3602 + %5230 = OpFMul %float %3604 %3604 + %5233 = OpFMul %float %3606 %3606 + %3615 = OpCompositeExtract %float %5111 0 + %3617 = OpCompositeExtract %float %5111 1 + %3619 = OpCompositeExtract %float %5111 2 + %5237 = OpFMul %float %3615 %3615 + %5240 = OpFMul %float %3617 %3617 + %5243 = OpFMul %float %3619 %3619 + %3628 = OpCompositeExtract %float %5118 0 + %3630 = OpCompositeExtract %float %5118 1 + %3632 = OpCompositeExtract %float %5118 2 + %5247 = OpFMul %float %3628 %3628 + %5250 = OpFMul %float %3630 %3630 + %5253 = OpFMul %float %3632 %3632 + %3654 = OpCompositeExtract %float %5104 0 + %3656 = OpCompositeExtract %float %5104 1 + %3658 = OpCompositeExtract %float %5104 2 + %5267 = OpFMul %float %3654 %3654 + %5270 = OpFMul %float %3656 %3656 + %5273 = OpFMul %float %3658 %3658 + %3667 = OpCompositeExtract %float %5125 0 + %3669 = OpCompositeExtract %float %5125 1 + %3671 = OpCompositeExtract %float %5125 2 + %5277 = OpFMul %float %3667 %3667 + %5280 = OpFMul %float %3669 %3669 + %5283 = OpFMul %float %3671 %3671 + %5313 = OpExtInst %float %1 FMin %5180 %5190 + %5314 = OpExtInst %float %1 FMin %5150 %5313 + %5320 = OpExtInst %float %1 FMin %5200 %5230 + %5321 = OpExtInst %float %1 FMin %5314 %5320 + %5355 = OpExtInst %float %1 FMax %5180 %5190 + %5356 = OpExtInst %float %1 FMax %5150 %5355 + %5362 = OpExtInst %float %1 FMax %5200 %5230 + %5363 = OpExtInst %float %1 FMax %5356 %5362 + %5397 = OpExtInst %float %1 FMin %5190 %5200 + %5398 = OpExtInst %float %1 FMin %5160 %5397 + %5404 = OpExtInst %float %1 FMin %5210 %5240 + %5405 = OpExtInst %float %1 FMin %5398 %5404 + %5439 = OpExtInst %float %1 FMax %5190 %5200 + %5440 = OpExtInst %float %1 FMax %5160 %5439 + %5446 = OpExtInst %float %1 FMax %5210 %5240 + %5447 = OpExtInst %float %1 FMax %5440 %5446 + %5481 = OpExtInst %float %1 FMin %5220 %5230 + %5482 = OpExtInst %float %1 FMin %5190 %5481 + %5488 = OpExtInst %float %1 FMin %5240 %5270 + %5489 = OpExtInst %float %1 FMin %5482 %5488 + %5523 = OpExtInst %float %1 FMax %5220 %5230 + %5524 = OpExtInst %float %1 FMax %5190 %5523 + %5530 = OpExtInst %float %1 FMax %5240 %5270 + %5531 = OpExtInst %float %1 FMax %5524 %5530 + %5565 = OpExtInst %float %1 FMin %5230 %5240 + %5566 = OpExtInst %float %1 FMin %5200 %5565 + %5572 = OpExtInst %float %1 FMin %5250 %5280 + %5573 = OpExtInst %float %1 FMin %5566 %5572 + %5607 = OpExtInst %float %1 FMax %5230 %5240 + %5608 = OpExtInst %float %1 FMax %5200 %5607 + %5614 = OpExtInst %float %1 FMax %5250 %5280 + %5615 = OpExtInst %float %1 FMax %5608 %5614 + %5646 = OpBitcast %uint %5363 + %5647 = OpISub %uint %uint_2129690299 %5646 + %5648 = OpBitcast %float %5647 + %5679 = OpBitcast %uint %5447 + %5680 = OpISub %uint %uint_2129690299 %5679 + %5681 = OpBitcast %float %5680 + %5712 = OpBitcast %uint %5531 + %5713 = OpISub %uint %uint_2129690299 %5712 + %5714 = OpBitcast %float %5713 + %5745 = OpBitcast %uint %5615 + %5746 = OpISub %uint %uint_2129690299 %5745 + %5747 = OpBitcast %float %5746 + %4015 = OpFSub %float %float_1 %5363 + %4016 = OpExtInst %float %1 FMin %5321 %4015 + %4018 = OpFMul %float %4016 %5648 + %5789 = OpExtInst %float %1 FClamp %4018 %float_0 %float_1 + %4039 = OpFSub %float %float_1 %5447 + %4040 = OpExtInst %float %1 FMin %5405 %4039 + %4042 = OpFMul %float %4040 %5681 + %5840 = OpExtInst %float %1 FClamp %4042 %float_0 %float_1 + %4063 = OpFSub %float %float_1 %5531 + %4064 = OpExtInst %float %1 FMin %5489 %4063 + %4066 = OpFMul %float %4064 %5714 + %5891 = OpExtInst %float %1 FClamp %4066 %float_0 %float_1 + %4087 = OpFSub %float %float_1 %5615 + %4088 = OpExtInst %float %1 FMin %5573 %4087 + %4090 = OpFMul %float %4088 %5747 + %5942 = OpExtInst %float %1 FClamp %4090 %float_0 %float_1 + %5988 = OpBitcast %uint %5789 + %5990 = OpShiftRightLogical %uint %5988 %uint_1 + %5992 = OpIAdd %uint %5990 %uint_532432441 + %5993 = OpBitcast %float %5992 + %6039 = OpBitcast %uint %5840 + %6041 = OpShiftRightLogical %uint %6039 %uint_1 + %6043 = OpIAdd %uint %6041 %uint_532432441 + %6044 = OpBitcast %float %6043 + %6090 = OpBitcast %uint %5891 + %6092 = OpShiftRightLogical %uint %6090 %uint_1 + %6094 = OpIAdd %uint %6092 %uint_532432441 + %6095 = OpBitcast %float %6094 + %6141 = OpBitcast %uint %5942 + %6143 = OpShiftRightLogical %uint %6141 %uint_1 + %6145 = OpIAdd %uint %6143 %uint_532432441 + %6146 = OpBitcast %float %6145 + %4126 = OpBitcast %float %2503 + %4132 = OpFMul %float %5993 %4126 + %4141 = OpFMul %float %6044 %4126 + %4150 = OpFMul %float %6095 %4126 + %4159 = OpFMul %float %6146 %4126 + %4165 = OpCompositeExtract %float %3434 0 + %4166 = OpFSub %float %float_1 %4165 + %4169 = OpCompositeExtract %float %3434 1 + %4170 = OpFSub %float %float_1 %4169 + %4171 = OpFMul %float %4166 %4170 + %4178 = OpFMul %float %4165 %4170 + %4185 = OpFMul %float %4166 %4169 + %4190 = OpFMul %float %4165 %4169 + %4194 = OpFSub %float %5363 %5321 + %4195 = OpFAdd %float %float_0_03125 %4194 + %6187 = OpBitcast %uint %4195 + %6188 = OpISub %uint %uint_2129690299 %6187 + %6189 = OpBitcast %float %6188 + %4198 = OpFMul %float %4171 %6189 + %4202 = OpFSub %float %5447 %5405 + %4203 = OpFAdd %float %float_0_03125 %4202 + %6198 = OpBitcast %uint %4203 + %6199 = OpISub %uint %uint_2129690299 %6198 + %6200 = OpBitcast %float %6199 + %4206 = OpFMul %float %4178 %6200 + %4210 = OpFSub %float %5531 %5489 + %4211 = OpFAdd %float %float_0_03125 %4210 + %6209 = OpBitcast %uint %4211 + %6210 = OpISub %uint %uint_2129690299 %6209 + %6211 = OpBitcast %float %6210 + %4214 = OpFMul %float %4185 %6211 + %4218 = OpFSub %float %5615 %5573 + %4219 = OpFAdd %float %float_0_03125 %4218 + %6220 = OpBitcast %uint %4219 + %6221 = OpISub %uint %uint_2129690299 %6220 + %6222 = OpBitcast %float %6221 + %4222 = OpFMul %float %4190 %6222 + %4228 = OpFMul %float %4132 %4198 + %4237 = OpFMul %float %4141 %4206 + %4255 = OpFMul %float %4150 %4214 + %4256 = OpFAdd %float %4237 %4255 + %4258 = OpFAdd %float %4256 %4198 + %4282 = OpFMul %float %4159 %4222 + %4283 = OpFAdd %float %4228 %4282 + %4285 = OpFAdd %float %4283 %4206 + %4312 = OpFAdd %float %4283 %4214 + %4339 = OpFAdd %float %4256 %4222 + %6763 = OpFAdd %float %4228 %4237 + %6764 = OpFAdd %float %6763 %4255 + %6765 = OpFAdd %float %6764 %4282 + %4381 = OpFMul %float %float_2 %6765 + %4383 = OpFAdd %float %4381 %4258 + %4385 = OpFAdd %float %4383 %4285 + %4387 = OpFAdd %float %4385 %4312 + %4389 = OpFAdd %float %4387 %4339 + %6245 = OpBitcast %uint %4389 + %6246 = OpISub %uint %uint_2129764351 %6245 + %6247 = OpBitcast %float %6246 + %6250 = OpFNegate %float %6247 + %6252 = OpFMul %float %6250 %4389 + %6254 = OpFAdd %float %6252 %float_2 + %6255 = OpFMul %float %6247 %6254 + %6766 = OpFAdd %float %5147 %5177 + %4399 = OpFMul %float %4228 %6766 + %4403 = OpFMul %float %5157 %4237 + %4404 = OpFAdd %float %4399 %4403 + %4408 = OpFMul %float %5207 %4237 + %4409 = OpFAdd %float %4404 %4408 + %4413 = OpFMul %float %5217 %4255 + %4414 = OpFAdd %float %4409 %4413 + %4418 = OpFMul %float %5267 %4255 + %4419 = OpFAdd %float %4414 %4418 + %4423 = OpFMul %float %5247 %4282 + %4424 = OpFAdd %float %4419 %4423 + %4428 = OpFMul %float %5277 %4282 + %4429 = OpFAdd %float %4424 %4428 + %4433 = OpFMul %float %5187 %4258 + %4434 = OpFAdd %float %4429 %4433 + %4438 = OpFMul %float %5197 %4285 + %4439 = OpFAdd %float %4434 %4438 + %4443 = OpFMul %float %5227 %4312 + %4444 = OpFAdd %float %4439 %4443 + %4448 = OpFMul %float %5237 %4339 + %4449 = OpFAdd %float %4444 %4448 + %4451 = OpFMul %float %4449 %6255 + %6269 = OpExtInst %float %1 FClamp %4451 %float_0 %float_1 + %6767 = OpFAdd %float %5150 %5180 + %4461 = OpFMul %float %4228 %6767 + %4465 = OpFMul %float %5160 %4237 + %4466 = OpFAdd %float %4461 %4465 + %4470 = OpFMul %float %5210 %4237 + %4471 = OpFAdd %float %4466 %4470 + %4475 = OpFMul %float %5220 %4255 + %4476 = OpFAdd %float %4471 %4475 + %4480 = OpFMul %float %5270 %4255 + %4481 = OpFAdd %float %4476 %4480 + %4485 = OpFMul %float %5250 %4282 + %4486 = OpFAdd %float %4481 %4485 + %4490 = OpFMul %float %5280 %4282 + %4491 = OpFAdd %float %4486 %4490 + %4495 = OpFMul %float %5190 %4258 + %4496 = OpFAdd %float %4491 %4495 + %4500 = OpFMul %float %5200 %4285 + %4501 = OpFAdd %float %4496 %4500 + %4505 = OpFMul %float %5230 %4312 + %4506 = OpFAdd %float %4501 %4505 + %4510 = OpFMul %float %5240 %4339 + %4511 = OpFAdd %float %4506 %4510 + %4513 = OpFMul %float %4511 %6255 + %6283 = OpExtInst %float %1 FClamp %4513 %float_0 %float_1 + %6768 = OpFAdd %float %5153 %5183 + %4523 = OpFMul %float %4228 %6768 + %4527 = OpFMul %float %5163 %4237 + %4528 = OpFAdd %float %4523 %4527 + %4532 = OpFMul %float %5213 %4237 + %4533 = OpFAdd %float %4528 %4532 + %4537 = OpFMul %float %5223 %4255 + %4538 = OpFAdd %float %4533 %4537 + %4542 = OpFMul %float %5273 %4255 + %4543 = OpFAdd %float %4538 %4542 + %4547 = OpFMul %float %5253 %4282 + %4548 = OpFAdd %float %4543 %4547 + %4552 = OpFMul %float %5283 %4282 + %4553 = OpFAdd %float %4548 %4552 + %4557 = OpFMul %float %5193 %4258 + %4558 = OpFAdd %float %4553 %4557 + %4562 = OpFMul %float %5203 %4285 + %4563 = OpFAdd %float %4558 %4562 + %4567 = OpFMul %float %5233 %4312 + %4568 = OpFAdd %float %4563 %4567 + %4572 = OpFMul %float %5243 %4339 + %4573 = OpFAdd %float %4568 %4572 + %4575 = OpFMul %float %4573 %6255 + %6297 = OpExtInst %float %1 FClamp %4575 %float_0 %float_1 + %2527 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %2527 %6269 + %2529 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %2529 %6283 + %2531 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %2531 %6297 + %2532 = OpLoad %v4float %xe_frag_color + %2533 = OpVectorShuffle %v3float %2532 %2532 0 1 2 + %2534 = OpExtInst %v3float %1 Sqrt %2533 + %2536 = OpCompositeExtract %float %2534 0 + OpStore %2527 %2536 + %2538 = OpCompositeExtract %float %2534 1 + OpStore %2529 %2538 + %2540 = OpCompositeExtract %float %2534 2 + OpStore %2531 %2540 + %2541 = OpLoad %v4float %xe_frag_color + %2542 = OpVectorShuffle %v3float %2541 %2541 0 1 2 + %6309 = OpBitwiseAnd %v2uint %2495 %6778 + %6311 = OpCompositeExtract %uint %6309 1 + %6312 = OpIMul %uint %6311 %uint_16 + %6314 = OpCompositeExtract %uint %6309 0 + %6315 = OpIAdd %uint %6312 %6314 + OpStore %6304 %337 + %6316 = OpAccessChain %_ptr_Function_float %6304 %6315 + %6317 = OpLoad %float %6316 + %2546 = OpCompositeConstruct %v3float %6317 %6317 %6317 + %2547 = OpFAdd %v3float %2542 %2546 + %2550 = OpExtInst %v3float %1 FClamp %2547 %2548 %2549 + %2552 = OpCompositeExtract %float %2550 0 + OpStore %2527 %2552 + %2554 = OpCompositeExtract %float %2550 1 + OpStore %2529 %2554 + %2556 = OpCompositeExtract %float %2550 2 + OpStore %2531 %2556 + %2558 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %2558 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h new file mode 100644 index 000000000..511585966 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h @@ -0,0 +1,723 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_cas_sharpen.frag +const uint8_t guest_output_ffx_cas_sharpen_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x39, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x92, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x58, 0x65, 0x43, 0x61, 0x73, 0x53, 0x68, 0x61, + 0x72, 0x70, 0x65, 0x6E, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, + 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x6F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x73, + 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 0x73, 0x5F, 0x70, 0x6F, 0x73, + 0x74, 0x5F, 0x73, 0x65, 0x74, 0x75, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xB8, 0x08, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, + 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x92, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x9C, 0x08, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x39, 0x46, 0xBC, 0x1F, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x19, 0x00, 0x09, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x91, 0x00, 0x00, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xD8, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xC8, 0x02, 0x00, 0x00, + 0xBC, 0x02, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xDE, 0x02, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0xBC, 0x02, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xE9, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xEF, 0x02, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, + 0x20, 0x00, 0x04, 0x00, 0x9B, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x9B, 0x08, 0x00, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xA1, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xA1, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xA3, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xAC, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xB7, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xB7, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xC6, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xD5, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x9E, 0x08, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x9F, 0x08, 0x00, 0x00, 0x9E, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xA3, 0x08, 0x00, 0x00, 0xA4, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xA5, 0x08, 0x00, 0x00, 0xA4, 0x08, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xA6, 0x08, 0x00, 0x00, + 0x9F, 0x08, 0x00, 0x00, 0xA5, 0x08, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x37, 0x00, 0x00, 0x00, 0xA7, 0x08, 0x00, 0x00, 0xA6, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xAC, 0x08, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAE, 0x08, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xAF, 0x08, 0x00, 0x00, + 0xAE, 0x08, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xD0, 0x0A, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0xD0, 0x0A, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x2F, 0x0C, 0x00, 0x00, 0xA7, 0x08, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x86, 0x02, 0x00, 0x00, 0x3F, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2F, 0x0C, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, 0x42, 0x0C, 0x00, 0x00, + 0x2F, 0x0C, 0x00, 0x00, 0x3F, 0x0C, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, 0x3F, 0x0C, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x49, 0x0C, 0x00, 0x00, + 0x44, 0x0C, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x7F, 0x12, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x81, 0x12, 0x00, 0x00, + 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x82, 0x12, 0x00, 0x00, 0x81, 0x12, 0x00, 0x00, 0x49, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x4C, 0x0C, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x88, 0x12, 0x00, 0x00, 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x89, 0x12, 0x00, 0x00, 0x88, 0x12, 0x00, 0x00, + 0x4C, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x8F, 0x12, 0x00, 0x00, + 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x90, 0x12, 0x00, 0x00, 0x8F, 0x12, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x96, 0x12, 0x00, 0x00, 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x97, 0x12, 0x00, 0x00, 0x96, 0x12, 0x00, 0x00, + 0x51, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x57, 0x0C, 0x00, 0x00, + 0x44, 0x0C, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xA4, 0x12, 0x00, 0x00, 0x7F, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xA5, 0x12, 0x00, 0x00, + 0xA4, 0x12, 0x00, 0x00, 0x57, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x5A, 0x0C, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, 0xC8, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xAB, 0x12, 0x00, 0x00, + 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xAC, 0x12, 0x00, 0x00, 0xAB, 0x12, 0x00, 0x00, 0x5A, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x5D, 0x0C, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, + 0xD2, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xB2, 0x12, 0x00, 0x00, 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xB3, 0x12, 0x00, 0x00, 0xB2, 0x12, 0x00, 0x00, + 0x5D, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x60, 0x0C, 0x00, 0x00, + 0x44, 0x0C, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xB9, 0x12, 0x00, 0x00, 0x7F, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xBA, 0x12, 0x00, 0x00, + 0xB9, 0x12, 0x00, 0x00, 0x60, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x66, 0x0C, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, 0xDE, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xC7, 0x12, 0x00, 0x00, + 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xC8, 0x12, 0x00, 0x00, 0xC7, 0x12, 0x00, 0x00, 0x66, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x69, 0x0C, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xCE, 0x12, 0x00, 0x00, 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xCF, 0x12, 0x00, 0x00, 0xCE, 0x12, 0x00, 0x00, + 0x69, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x6C, 0x0C, 0x00, 0x00, + 0x44, 0x0C, 0x00, 0x00, 0xE9, 0x02, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xD5, 0x12, 0x00, 0x00, 0x7F, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xD6, 0x12, 0x00, 0x00, + 0xD5, 0x12, 0x00, 0x00, 0x6C, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x6F, 0x0C, 0x00, 0x00, 0x44, 0x0C, 0x00, 0x00, 0xEF, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xDC, 0x12, 0x00, 0x00, + 0x7F, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xDD, 0x12, 0x00, 0x00, 0xDC, 0x12, 0x00, 0x00, 0x6F, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x82, 0x0C, 0x00, 0x00, 0x82, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x84, 0x0C, 0x00, 0x00, 0x82, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x86, 0x0C, 0x00, 0x00, + 0x82, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF3, 0x12, 0x00, 0x00, 0x82, 0x0C, 0x00, 0x00, + 0x82, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF6, 0x12, 0x00, 0x00, 0x84, 0x0C, 0x00, 0x00, 0x84, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF9, 0x12, 0x00, 0x00, + 0x86, 0x0C, 0x00, 0x00, 0x86, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8F, 0x0C, 0x00, 0x00, 0x97, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x91, 0x0C, 0x00, 0x00, 0x97, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x0C, 0x00, 0x00, + 0x97, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFD, 0x12, 0x00, 0x00, 0x8F, 0x0C, 0x00, 0x00, + 0x8F, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x13, 0x00, 0x00, 0x91, 0x0C, 0x00, 0x00, 0x91, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x13, 0x00, 0x00, + 0x93, 0x0C, 0x00, 0x00, 0x93, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA9, 0x0C, 0x00, 0x00, 0x89, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAB, 0x0C, 0x00, 0x00, 0x89, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAD, 0x0C, 0x00, 0x00, + 0x89, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x11, 0x13, 0x00, 0x00, 0xA9, 0x0C, 0x00, 0x00, + 0xA9, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x14, 0x13, 0x00, 0x00, 0xAB, 0x0C, 0x00, 0x00, 0xAB, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17, 0x13, 0x00, 0x00, + 0xAD, 0x0C, 0x00, 0x00, 0xAD, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB6, 0x0C, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB8, 0x0C, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBA, 0x0C, 0x00, 0x00, + 0x90, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1B, 0x13, 0x00, 0x00, 0xB6, 0x0C, 0x00, 0x00, + 0xB6, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1E, 0x13, 0x00, 0x00, 0xB8, 0x0C, 0x00, 0x00, 0xB8, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x13, 0x00, 0x00, + 0xBA, 0x0C, 0x00, 0x00, 0xBA, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, 0xA5, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC5, 0x0C, 0x00, 0x00, 0xA5, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC7, 0x0C, 0x00, 0x00, + 0xA5, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x25, 0x13, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, + 0xC3, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x28, 0x13, 0x00, 0x00, 0xC5, 0x0C, 0x00, 0x00, 0xC5, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x13, 0x00, 0x00, + 0xC7, 0x0C, 0x00, 0x00, 0xC7, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, 0xAC, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD2, 0x0C, 0x00, 0x00, 0xAC, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD4, 0x0C, 0x00, 0x00, + 0xAC, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2F, 0x13, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, + 0xD0, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x32, 0x13, 0x00, 0x00, 0xD2, 0x0C, 0x00, 0x00, 0xD2, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x13, 0x00, 0x00, + 0xD4, 0x0C, 0x00, 0x00, 0xD4, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDD, 0x0C, 0x00, 0x00, 0xB3, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDF, 0x0C, 0x00, 0x00, 0xB3, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE1, 0x0C, 0x00, 0x00, + 0xB3, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x39, 0x13, 0x00, 0x00, 0xDD, 0x0C, 0x00, 0x00, + 0xDD, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3C, 0x13, 0x00, 0x00, 0xDF, 0x0C, 0x00, 0x00, 0xDF, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3F, 0x13, 0x00, 0x00, + 0xE1, 0x0C, 0x00, 0x00, 0xE1, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, 0xBA, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEC, 0x0C, 0x00, 0x00, 0xBA, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEE, 0x0C, 0x00, 0x00, + 0xBA, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x43, 0x13, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, + 0xEA, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x46, 0x13, 0x00, 0x00, 0xEC, 0x0C, 0x00, 0x00, 0xEC, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x49, 0x13, 0x00, 0x00, + 0xEE, 0x0C, 0x00, 0x00, 0xEE, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF7, 0x0C, 0x00, 0x00, 0xCF, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF9, 0x0C, 0x00, 0x00, 0xCF, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFB, 0x0C, 0x00, 0x00, + 0xCF, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4D, 0x13, 0x00, 0x00, 0xF7, 0x0C, 0x00, 0x00, + 0xF7, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x50, 0x13, 0x00, 0x00, 0xF9, 0x0C, 0x00, 0x00, 0xF9, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, + 0xFB, 0x0C, 0x00, 0x00, 0xFB, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x0D, 0x00, 0x00, 0xD6, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x0D, 0x00, 0x00, 0xD6, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, + 0xD6, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x57, 0x13, 0x00, 0x00, 0x04, 0x0D, 0x00, 0x00, + 0x04, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5A, 0x13, 0x00, 0x00, 0x06, 0x0D, 0x00, 0x00, 0x06, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, + 0x08, 0x0D, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1E, 0x0D, 0x00, 0x00, 0xC8, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x0D, 0x00, 0x00, 0xC8, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x00, + 0xC8, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6B, 0x13, 0x00, 0x00, 0x1E, 0x0D, 0x00, 0x00, + 0x1E, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6E, 0x13, 0x00, 0x00, 0x20, 0x0D, 0x00, 0x00, 0x20, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, 0x13, 0x00, 0x00, + 0x22, 0x0D, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, 0xDD, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2D, 0x0D, 0x00, 0x00, 0xDD, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, + 0xDD, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x75, 0x13, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, + 0x2B, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x78, 0x13, 0x00, 0x00, 0x2D, 0x0D, 0x00, 0x00, 0x2D, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7B, 0x13, 0x00, 0x00, + 0x2F, 0x0D, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x99, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x14, 0x13, 0x00, 0x00, 0x1E, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9A, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xF6, 0x12, 0x00, 0x00, + 0x99, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA0, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x28, 0x13, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA1, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x9A, 0x13, 0x00, 0x00, 0xA0, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC3, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x14, 0x13, 0x00, 0x00, + 0x1E, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC4, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xF6, 0x12, 0x00, 0x00, 0xC3, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCA, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x13, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCB, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xC4, 0x13, 0x00, 0x00, + 0xCA, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xED, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x1E, 0x13, 0x00, 0x00, 0x28, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEE, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0xED, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF4, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x32, 0x13, 0x00, 0x00, + 0x50, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF5, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xEE, 0x13, 0x00, 0x00, 0xF4, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x17, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x1E, 0x13, 0x00, 0x00, 0x28, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, + 0x17, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1E, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x32, 0x13, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x18, 0x14, 0x00, 0x00, 0x1E, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3C, 0x13, 0x00, 0x00, + 0x46, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x42, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x1E, 0x13, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, 0x6E, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x49, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x42, 0x14, 0x00, 0x00, + 0x48, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6B, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x3C, 0x13, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6C, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x1E, 0x13, 0x00, 0x00, 0x6B, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x72, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, + 0x6E, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x73, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x6C, 0x14, 0x00, 0x00, 0x72, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x95, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x96, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x28, 0x13, 0x00, 0x00, + 0x95, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9C, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x5A, 0x13, 0x00, 0x00, 0x78, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9D, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x96, 0x14, 0x00, 0x00, 0x9C, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBF, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, + 0x50, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC0, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x28, 0x13, 0x00, 0x00, 0xBF, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC6, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x5A, 0x13, 0x00, 0x00, 0x78, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC7, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xC0, 0x14, 0x00, 0x00, + 0xC6, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xE6, 0x14, 0x00, 0x00, 0xCB, 0x13, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE7, 0x14, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xE6, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE8, 0x14, 0x00, 0x00, 0xE7, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x07, 0x15, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x15, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x07, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x09, 0x15, 0x00, 0x00, 0x08, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x28, 0x15, 0x00, 0x00, + 0x73, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x29, 0x15, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x28, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2A, 0x15, 0x00, 0x00, + 0x29, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x49, 0x15, 0x00, 0x00, 0xC7, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x4A, 0x15, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x49, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x15, 0x00, 0x00, 0x4A, 0x15, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x87, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xCB, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x88, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xA1, 0x13, 0x00, 0x00, 0x87, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8A, 0x0E, 0x00, 0x00, 0x88, 0x0E, 0x00, 0x00, + 0xE8, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x75, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x8A, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9F, 0x0E, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA0, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xF5, 0x13, 0x00, 0x00, 0x9F, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA2, 0x0E, 0x00, 0x00, + 0xA0, 0x0E, 0x00, 0x00, 0x09, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA8, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xA2, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB7, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x73, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB8, 0x0E, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x49, 0x14, 0x00, 0x00, + 0xB7, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBA, 0x0E, 0x00, 0x00, 0xB8, 0x0E, 0x00, 0x00, 0x2A, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDB, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xBA, 0x0E, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCF, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xC7, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD0, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x9D, 0x14, 0x00, 0x00, 0xCF, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD2, 0x0E, 0x00, 0x00, 0xD0, 0x0E, 0x00, 0x00, + 0x4B, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0E, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xD2, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, + 0x75, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x3E, 0x16, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x40, 0x16, 0x00, 0x00, + 0x3E, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x41, 0x16, 0x00, 0x00, 0x40, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6F, 0x16, 0x00, 0x00, + 0xA8, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x71, 0x16, 0x00, 0x00, 0x6F, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x73, 0x16, 0x00, 0x00, + 0x71, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x74, 0x16, 0x00, 0x00, 0x73, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xA2, 0x16, 0x00, 0x00, + 0xDB, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xA4, 0x16, 0x00, 0x00, 0xA2, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xA6, 0x16, 0x00, 0x00, + 0xA4, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA7, 0x16, 0x00, 0x00, 0xA6, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xD5, 0x16, 0x00, 0x00, + 0x0E, 0x16, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xD7, 0x16, 0x00, 0x00, 0xD5, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xD9, 0x16, 0x00, 0x00, + 0xD7, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDA, 0x16, 0x00, 0x00, 0xD9, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF6, 0x0E, 0x00, 0x00, + 0xAF, 0x08, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFC, 0x0E, 0x00, 0x00, 0x41, 0x16, 0x00, 0x00, 0xF6, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x0F, 0x00, 0x00, + 0x74, 0x16, 0x00, 0x00, 0xF6, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x0F, 0x00, 0x00, 0xA7, 0x16, 0x00, 0x00, + 0xF6, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x17, 0x0F, 0x00, 0x00, 0xDA, 0x16, 0x00, 0x00, 0xF6, 0x0E, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1D, 0x0F, 0x00, 0x00, + 0x42, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1E, 0x0F, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x1D, 0x0F, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x21, 0x0F, 0x00, 0x00, 0x42, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x0F, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x21, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x23, 0x0F, 0x00, 0x00, 0x1E, 0x0F, 0x00, 0x00, + 0x22, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2A, 0x0F, 0x00, 0x00, 0x1D, 0x0F, 0x00, 0x00, 0x22, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x31, 0x0F, 0x00, 0x00, + 0x1E, 0x0F, 0x00, 0x00, 0x21, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x36, 0x0F, 0x00, 0x00, 0x1D, 0x0F, 0x00, 0x00, + 0x21, 0x0F, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3A, 0x0F, 0x00, 0x00, 0xCB, 0x13, 0x00, 0x00, 0xA1, 0x13, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x0F, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x3A, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x03, 0x17, 0x00, 0x00, 0x3B, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x17, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x03, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x04, 0x17, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3E, 0x0F, 0x00, 0x00, + 0x23, 0x0F, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x42, 0x0F, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, + 0xF5, 0x13, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x43, 0x0F, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, 0x42, 0x0F, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x17, 0x00, 0x00, + 0x43, 0x0F, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0F, 0x17, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x0E, 0x17, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x17, 0x00, 0x00, + 0x0F, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x46, 0x0F, 0x00, 0x00, 0x2A, 0x0F, 0x00, 0x00, 0x10, 0x17, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x0F, 0x00, 0x00, + 0x73, 0x14, 0x00, 0x00, 0x49, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4B, 0x0F, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, + 0x4A, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x19, 0x17, 0x00, 0x00, 0x4B, 0x0F, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x1A, 0x17, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x19, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1B, 0x17, 0x00, 0x00, 0x1A, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4E, 0x0F, 0x00, 0x00, 0x31, 0x0F, 0x00, 0x00, + 0x1B, 0x17, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x52, 0x0F, 0x00, 0x00, 0xC7, 0x14, 0x00, 0x00, 0x9D, 0x14, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x0F, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x52, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x24, 0x17, 0x00, 0x00, 0x53, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x25, 0x17, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x24, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x26, 0x17, 0x00, 0x00, 0x25, 0x17, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x0F, 0x00, 0x00, + 0x36, 0x0F, 0x00, 0x00, 0x26, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5C, 0x0F, 0x00, 0x00, 0xFC, 0x0E, 0x00, 0x00, + 0x3E, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x65, 0x0F, 0x00, 0x00, 0x05, 0x0F, 0x00, 0x00, 0x46, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x0F, 0x00, 0x00, + 0x0E, 0x0F, 0x00, 0x00, 0x4E, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x78, 0x0F, 0x00, 0x00, 0x65, 0x0F, 0x00, 0x00, + 0x77, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7A, 0x0F, 0x00, 0x00, 0x78, 0x0F, 0x00, 0x00, 0x3E, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x92, 0x0F, 0x00, 0x00, + 0x17, 0x0F, 0x00, 0x00, 0x56, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x93, 0x0F, 0x00, 0x00, 0x5C, 0x0F, 0x00, 0x00, + 0x92, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x95, 0x0F, 0x00, 0x00, 0x93, 0x0F, 0x00, 0x00, 0x46, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB0, 0x0F, 0x00, 0x00, + 0x93, 0x0F, 0x00, 0x00, 0x4E, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCB, 0x0F, 0x00, 0x00, 0x78, 0x0F, 0x00, 0x00, + 0x56, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x33, 0x19, 0x00, 0x00, 0x5C, 0x0F, 0x00, 0x00, 0x65, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x19, 0x00, 0x00, + 0x33, 0x19, 0x00, 0x00, 0x77, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x35, 0x19, 0x00, 0x00, 0x34, 0x19, 0x00, 0x00, + 0x92, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF5, 0x0F, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x35, 0x19, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF7, 0x0F, 0x00, 0x00, + 0xF5, 0x0F, 0x00, 0x00, 0x7A, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF9, 0x0F, 0x00, 0x00, 0xF7, 0x0F, 0x00, 0x00, + 0x95, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFB, 0x0F, 0x00, 0x00, 0xF9, 0x0F, 0x00, 0x00, 0xB0, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFD, 0x0F, 0x00, 0x00, + 0xFB, 0x0F, 0x00, 0x00, 0xCB, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x17, 0x00, 0x00, 0xFD, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3E, 0x17, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x3D, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3F, 0x17, 0x00, 0x00, 0x3E, 0x17, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x17, 0x00, 0x00, + 0x3F, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x44, 0x17, 0x00, 0x00, 0x42, 0x17, 0x00, 0x00, 0xFD, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, + 0x44, 0x17, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x47, 0x17, 0x00, 0x00, 0x3F, 0x17, 0x00, 0x00, + 0x46, 0x17, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x36, 0x19, 0x00, 0x00, 0xF3, 0x12, 0x00, 0x00, 0x11, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, + 0x5C, 0x0F, 0x00, 0x00, 0x36, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0B, 0x10, 0x00, 0x00, 0xFD, 0x12, 0x00, 0x00, + 0x65, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x10, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x0B, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x2F, 0x13, 0x00, 0x00, 0x65, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x11, 0x10, 0x00, 0x00, 0x0C, 0x10, 0x00, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x15, 0x10, 0x00, 0x00, 0x39, 0x13, 0x00, 0x00, 0x77, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, + 0x11, 0x10, 0x00, 0x00, 0x15, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1A, 0x10, 0x00, 0x00, 0x6B, 0x13, 0x00, 0x00, + 0x77, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1B, 0x10, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, 0x1A, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x00, 0x00, + 0x57, 0x13, 0x00, 0x00, 0x92, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x1B, 0x10, 0x00, 0x00, + 0x1F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x24, 0x10, 0x00, 0x00, 0x75, 0x13, 0x00, 0x00, 0x92, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x10, 0x00, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x1B, 0x13, 0x00, 0x00, + 0x7A, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2A, 0x10, 0x00, 0x00, 0x25, 0x10, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2E, 0x10, 0x00, 0x00, + 0x25, 0x13, 0x00, 0x00, 0x95, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2F, 0x10, 0x00, 0x00, 0x2A, 0x10, 0x00, 0x00, + 0x2E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x33, 0x10, 0x00, 0x00, 0x43, 0x13, 0x00, 0x00, 0xB0, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x10, 0x00, 0x00, + 0x2F, 0x10, 0x00, 0x00, 0x33, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x38, 0x10, 0x00, 0x00, 0x4D, 0x13, 0x00, 0x00, + 0xCB, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x39, 0x10, 0x00, 0x00, 0x34, 0x10, 0x00, 0x00, 0x38, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x10, 0x00, 0x00, + 0x39, 0x10, 0x00, 0x00, 0x47, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x55, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x3B, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x37, 0x19, 0x00, 0x00, 0xF6, 0x12, 0x00, 0x00, 0x14, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, + 0x5C, 0x0F, 0x00, 0x00, 0x37, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, + 0x65, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4A, 0x10, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4E, 0x10, 0x00, 0x00, + 0x32, 0x13, 0x00, 0x00, 0x65, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4F, 0x10, 0x00, 0x00, 0x4A, 0x10, 0x00, 0x00, + 0x4E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x53, 0x10, 0x00, 0x00, 0x3C, 0x13, 0x00, 0x00, 0x77, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00, + 0x4F, 0x10, 0x00, 0x00, 0x53, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x6E, 0x13, 0x00, 0x00, + 0x77, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x59, 0x10, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5D, 0x10, 0x00, 0x00, + 0x5A, 0x13, 0x00, 0x00, 0x92, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5E, 0x10, 0x00, 0x00, 0x59, 0x10, 0x00, 0x00, + 0x5D, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x62, 0x10, 0x00, 0x00, 0x78, 0x13, 0x00, 0x00, 0x92, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, + 0x5E, 0x10, 0x00, 0x00, 0x62, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x67, 0x10, 0x00, 0x00, 0x1E, 0x13, 0x00, 0x00, + 0x7A, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x68, 0x10, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, 0x67, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6C, 0x10, 0x00, 0x00, + 0x28, 0x13, 0x00, 0x00, 0x95, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6D, 0x10, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00, + 0x6C, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x71, 0x10, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, 0xB0, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x72, 0x10, 0x00, 0x00, + 0x6D, 0x10, 0x00, 0x00, 0x71, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x76, 0x10, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, + 0xCB, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x77, 0x10, 0x00, 0x00, 0x72, 0x10, 0x00, 0x00, 0x76, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x79, 0x10, 0x00, 0x00, + 0x77, 0x10, 0x00, 0x00, 0x47, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x63, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x79, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x38, 0x19, 0x00, 0x00, 0xF9, 0x12, 0x00, 0x00, 0x17, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, + 0x5C, 0x0F, 0x00, 0x00, 0x38, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, 0x03, 0x13, 0x00, 0x00, + 0x65, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x88, 0x10, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8C, 0x10, 0x00, 0x00, + 0x35, 0x13, 0x00, 0x00, 0x65, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, 0x88, 0x10, 0x00, 0x00, + 0x8C, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x91, 0x10, 0x00, 0x00, 0x3F, 0x13, 0x00, 0x00, 0x77, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x92, 0x10, 0x00, 0x00, + 0x8D, 0x10, 0x00, 0x00, 0x91, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x96, 0x10, 0x00, 0x00, 0x71, 0x13, 0x00, 0x00, + 0x77, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x97, 0x10, 0x00, 0x00, 0x92, 0x10, 0x00, 0x00, 0x96, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9B, 0x10, 0x00, 0x00, + 0x5D, 0x13, 0x00, 0x00, 0x92, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9C, 0x10, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, + 0x9B, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA0, 0x10, 0x00, 0x00, 0x7B, 0x13, 0x00, 0x00, 0x92, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA1, 0x10, 0x00, 0x00, + 0x9C, 0x10, 0x00, 0x00, 0xA0, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA5, 0x10, 0x00, 0x00, 0x21, 0x13, 0x00, 0x00, + 0x7A, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA6, 0x10, 0x00, 0x00, 0xA1, 0x10, 0x00, 0x00, 0xA5, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAA, 0x10, 0x00, 0x00, + 0x2B, 0x13, 0x00, 0x00, 0x95, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, 0xA6, 0x10, 0x00, 0x00, + 0xAA, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAF, 0x10, 0x00, 0x00, 0x49, 0x13, 0x00, 0x00, 0xB0, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, + 0xAB, 0x10, 0x00, 0x00, 0xAF, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB4, 0x10, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, + 0xCB, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB5, 0x10, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, 0xB4, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB7, 0x10, 0x00, 0x00, + 0xB5, 0x10, 0x00, 0x00, 0x47, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x71, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xB7, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xC6, 0x08, 0x00, 0x00, + 0xC7, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xC7, 0x08, 0x00, 0x00, 0x55, 0x17, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xC6, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0xB8, 0x08, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xC9, 0x08, 0x00, 0x00, 0x63, 0x17, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC6, 0x08, 0x00, 0x00, 0xCB, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xCB, 0x08, 0x00, 0x00, + 0x71, 0x17, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xCC, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0xCD, 0x08, 0x00, 0x00, 0xCC, 0x08, 0x00, 0x00, + 0xCC, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xCE, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0xCD, 0x08, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD0, 0x08, 0x00, 0x00, 0xCE, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xC7, 0x08, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD2, 0x08, 0x00, 0x00, + 0xCE, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xC9, 0x08, 0x00, 0x00, 0xD2, 0x08, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD4, 0x08, 0x00, 0x00, 0xCE, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xCB, 0x08, 0x00, 0x00, + 0xD4, 0x08, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xC6, 0x08, 0x00, 0x00, + 0xD6, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0xD5, 0x08, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xD6, 0x08, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.spv new file mode 100644 index 000000000..864ca097e Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.txt new file mode 100644 index 000000000..d3a317e9b --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.txt @@ -0,0 +1,433 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 6457 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeCasSharpenConstants "XeCasSharpenConstants" + OpMemberName %XeCasSharpenConstants 0 "xe_cas_output_offset" + OpMemberName %XeCasSharpenConstants 1 "xe_cas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeCasSharpenConstants 0 Offset 16 + OpMemberDecorate %XeCasSharpenConstants 1 Offset 24 + OpDecorate %XeCasSharpenConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %uint = OpTypeInt 32 0 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v3float = OpTypeVector %float 3 + %v2uint = OpTypeVector %uint 2 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 + %uint_1 = OpConstant %uint 1 +%uint_532432441 = OpConstant %uint 532432441 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %143 = OpTypeImage %float 2D 0 0 0 1 Unknown + %144 = OpTypeSampledImage %143 +%_ptr_UniformConstant_144 = OpTypePointer UniformConstant %144 + %xe_texture = OpVariable %_ptr_UniformConstant_144 UniformConstant + %int_0 = OpConstant %int 0 + %v4float = OpTypeVector %float 4 + %int_n1 = OpConstant %int -1 + %181 = OpConstantComposite %v2int %int_0 %int_n1 + %int_1 = OpConstant %int 1 + %188 = OpConstantComposite %v2int %int_1 %int_n1 + %194 = OpConstantComposite %v2int %int_n1 %int_0 + %204 = OpConstantComposite %v2int %int_1 %int_0 + %210 = OpConstantComposite %v2int %int_n1 %int_1 + %216 = OpConstantComposite %v2int %int_0 %int_1 + %222 = OpConstantComposite %v2int %int_1 %int_1 + %uint_0 = OpConstant %uint 0 + %uint_2 = OpConstant %uint 2 + %v2float = OpTypeVector %float 2 + %int_2 = OpConstant %int 2 + %712 = OpConstantComposite %v2int %int_2 %int_0 + %734 = OpConstantComposite %v2int %int_0 %int_2 + %745 = OpConstantComposite %v2int %int_2 %int_1 + %751 = OpConstantComposite %v2int %int_1 %int_2 +%float_0_03125 = OpConstant %float 0.03125 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeCasSharpenConstants = OpTypeStruct %v2int %float +%_ptr_PushConstant_XeCasSharpenConstants = OpTypePointer PushConstant %XeCasSharpenConstants + %_ = OpVariable %_ptr_PushConstant_XeCasSharpenConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %uint_3 = OpConstant %uint 3 + %main = OpFunction %void None %3 + %5 = OpLabel + %2205 = OpLoad %v4float %gl_FragCoord + %2206 = OpVectorShuffle %v2float %2205 %2205 0 1 + %2207 = OpConvertFToS %v2int %2206 + %2212 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %2213 = OpLoad %v2int %2212 + %2214 = OpISub %v2int %2207 %2213 + %2215 = OpBitcast %v2uint %2214 + %2221 = OpAccessChain %_ptr_PushConstant_float %_ %int_1 + %2222 = OpLoad %float %2221 + %2223 = OpBitcast %uint %2222 + OpBranch %2768 + %2768 = OpLabel + %3119 = OpConvertUToF %v2float %2215 + %3135 = OpExtInst %v2float %1 Floor %3119 + %3138 = OpFSub %v2float %3119 %3135 + %3140 = OpConvertFToS %v2int %3135 + %3145 = OpIAdd %v2int %3140 %181 + %4735 = OpLoad %144 %xe_texture + %4737 = OpImage %143 %4735 + %4738 = OpImageFetch %v4float %4737 %3145 Lod %int_0 + %3148 = OpIAdd %v2int %3140 %194 + %4744 = OpImage %143 %4735 + %4745 = OpImageFetch %v4float %4744 %3148 Lod %int_0 + %4751 = OpImage %143 %4735 + %4752 = OpImageFetch %v4float %4751 %3140 Lod %int_0 + %3153 = OpIAdd %v2int %3140 %188 + %4758 = OpImage %143 %4735 + %4759 = OpImageFetch %v4float %4758 %3153 Lod %int_0 + %3159 = OpIAdd %v2int %3140 %204 + %4772 = OpImage %143 %4735 + %4773 = OpImageFetch %v4float %4772 %3159 Lod %int_0 + %3162 = OpIAdd %v2int %3140 %712 + %4779 = OpImage %143 %4735 + %4780 = OpImageFetch %v4float %4779 %3162 Lod %int_0 + %3165 = OpIAdd %v2int %3140 %210 + %4786 = OpImage %143 %4735 + %4787 = OpImageFetch %v4float %4786 %3165 Lod %int_0 + %3168 = OpIAdd %v2int %3140 %216 + %4793 = OpImage %143 %4735 + %4794 = OpImageFetch %v4float %4793 %3168 Lod %int_0 + %3174 = OpIAdd %v2int %3140 %734 + %4807 = OpImage %143 %4735 + %4808 = OpImageFetch %v4float %4807 %3174 Lod %int_0 + %3177 = OpIAdd %v2int %3140 %222 + %4814 = OpImage %143 %4735 + %4815 = OpImageFetch %v4float %4814 %3177 Lod %int_0 + %3180 = OpIAdd %v2int %3140 %745 + %4821 = OpImage %143 %4735 + %4822 = OpImageFetch %v4float %4821 %3180 Lod %int_0 + %3183 = OpIAdd %v2int %3140 %751 + %4828 = OpImage %143 %4735 + %4829 = OpImageFetch %v4float %4828 %3183 Lod %int_0 + %3202 = OpCompositeExtract %float %4738 0 + %3204 = OpCompositeExtract %float %4738 1 + %3206 = OpCompositeExtract %float %4738 2 + %4851 = OpFMul %float %3202 %3202 + %4854 = OpFMul %float %3204 %3204 + %4857 = OpFMul %float %3206 %3206 + %3215 = OpCompositeExtract %float %4759 0 + %3217 = OpCompositeExtract %float %4759 1 + %3219 = OpCompositeExtract %float %4759 2 + %4861 = OpFMul %float %3215 %3215 + %4864 = OpFMul %float %3217 %3217 + %4867 = OpFMul %float %3219 %3219 + %3241 = OpCompositeExtract %float %4745 0 + %3243 = OpCompositeExtract %float %4745 1 + %3245 = OpCompositeExtract %float %4745 2 + %4881 = OpFMul %float %3241 %3241 + %4884 = OpFMul %float %3243 %3243 + %4887 = OpFMul %float %3245 %3245 + %3254 = OpCompositeExtract %float %4752 0 + %3256 = OpCompositeExtract %float %4752 1 + %3258 = OpCompositeExtract %float %4752 2 + %4891 = OpFMul %float %3254 %3254 + %4894 = OpFMul %float %3256 %3256 + %4897 = OpFMul %float %3258 %3258 + %3267 = OpCompositeExtract %float %4773 0 + %3269 = OpCompositeExtract %float %4773 1 + %3271 = OpCompositeExtract %float %4773 2 + %4901 = OpFMul %float %3267 %3267 + %4904 = OpFMul %float %3269 %3269 + %4907 = OpFMul %float %3271 %3271 + %3280 = OpCompositeExtract %float %4780 0 + %3282 = OpCompositeExtract %float %4780 1 + %3284 = OpCompositeExtract %float %4780 2 + %4911 = OpFMul %float %3280 %3280 + %4914 = OpFMul %float %3282 %3282 + %4917 = OpFMul %float %3284 %3284 + %3293 = OpCompositeExtract %float %4787 0 + %3295 = OpCompositeExtract %float %4787 1 + %3297 = OpCompositeExtract %float %4787 2 + %4921 = OpFMul %float %3293 %3293 + %4924 = OpFMul %float %3295 %3295 + %4927 = OpFMul %float %3297 %3297 + %3306 = OpCompositeExtract %float %4794 0 + %3308 = OpCompositeExtract %float %4794 1 + %3310 = OpCompositeExtract %float %4794 2 + %4931 = OpFMul %float %3306 %3306 + %4934 = OpFMul %float %3308 %3308 + %4937 = OpFMul %float %3310 %3310 + %3319 = OpCompositeExtract %float %4815 0 + %3321 = OpCompositeExtract %float %4815 1 + %3323 = OpCompositeExtract %float %4815 2 + %4941 = OpFMul %float %3319 %3319 + %4944 = OpFMul %float %3321 %3321 + %4947 = OpFMul %float %3323 %3323 + %3332 = OpCompositeExtract %float %4822 0 + %3334 = OpCompositeExtract %float %4822 1 + %3336 = OpCompositeExtract %float %4822 2 + %4951 = OpFMul %float %3332 %3332 + %4954 = OpFMul %float %3334 %3334 + %4957 = OpFMul %float %3336 %3336 + %3358 = OpCompositeExtract %float %4808 0 + %3360 = OpCompositeExtract %float %4808 1 + %3362 = OpCompositeExtract %float %4808 2 + %4971 = OpFMul %float %3358 %3358 + %4974 = OpFMul %float %3360 %3360 + %4977 = OpFMul %float %3362 %3362 + %3371 = OpCompositeExtract %float %4829 0 + %3373 = OpCompositeExtract %float %4829 1 + %3375 = OpCompositeExtract %float %4829 2 + %4981 = OpFMul %float %3371 %3371 + %4984 = OpFMul %float %3373 %3373 + %4987 = OpFMul %float %3375 %3375 + %5017 = OpExtInst %float %1 FMin %4884 %4894 + %5018 = OpExtInst %float %1 FMin %4854 %5017 + %5024 = OpExtInst %float %1 FMin %4904 %4934 + %5025 = OpExtInst %float %1 FMin %5018 %5024 + %5059 = OpExtInst %float %1 FMax %4884 %4894 + %5060 = OpExtInst %float %1 FMax %4854 %5059 + %5066 = OpExtInst %float %1 FMax %4904 %4934 + %5067 = OpExtInst %float %1 FMax %5060 %5066 + %5101 = OpExtInst %float %1 FMin %4894 %4904 + %5102 = OpExtInst %float %1 FMin %4864 %5101 + %5108 = OpExtInst %float %1 FMin %4914 %4944 + %5109 = OpExtInst %float %1 FMin %5102 %5108 + %5143 = OpExtInst %float %1 FMax %4894 %4904 + %5144 = OpExtInst %float %1 FMax %4864 %5143 + %5150 = OpExtInst %float %1 FMax %4914 %4944 + %5151 = OpExtInst %float %1 FMax %5144 %5150 + %5185 = OpExtInst %float %1 FMin %4924 %4934 + %5186 = OpExtInst %float %1 FMin %4894 %5185 + %5192 = OpExtInst %float %1 FMin %4944 %4974 + %5193 = OpExtInst %float %1 FMin %5186 %5192 + %5227 = OpExtInst %float %1 FMax %4924 %4934 + %5228 = OpExtInst %float %1 FMax %4894 %5227 + %5234 = OpExtInst %float %1 FMax %4944 %4974 + %5235 = OpExtInst %float %1 FMax %5228 %5234 + %5269 = OpExtInst %float %1 FMin %4934 %4944 + %5270 = OpExtInst %float %1 FMin %4904 %5269 + %5276 = OpExtInst %float %1 FMin %4954 %4984 + %5277 = OpExtInst %float %1 FMin %5270 %5276 + %5311 = OpExtInst %float %1 FMax %4934 %4944 + %5312 = OpExtInst %float %1 FMax %4904 %5311 + %5318 = OpExtInst %float %1 FMax %4954 %4984 + %5319 = OpExtInst %float %1 FMax %5312 %5318 + %5350 = OpBitcast %uint %5067 + %5351 = OpISub %uint %uint_2129690299 %5350 + %5352 = OpBitcast %float %5351 + %5383 = OpBitcast %uint %5151 + %5384 = OpISub %uint %uint_2129690299 %5383 + %5385 = OpBitcast %float %5384 + %5416 = OpBitcast %uint %5235 + %5417 = OpISub %uint %uint_2129690299 %5416 + %5418 = OpBitcast %float %5417 + %5449 = OpBitcast %uint %5319 + %5450 = OpISub %uint %uint_2129690299 %5449 + %5451 = OpBitcast %float %5450 + %3719 = OpFSub %float %float_1 %5067 + %3720 = OpExtInst %float %1 FMin %5025 %3719 + %3722 = OpFMul %float %3720 %5352 + %5493 = OpExtInst %float %1 FClamp %3722 %float_0 %float_1 + %3743 = OpFSub %float %float_1 %5151 + %3744 = OpExtInst %float %1 FMin %5109 %3743 + %3746 = OpFMul %float %3744 %5385 + %5544 = OpExtInst %float %1 FClamp %3746 %float_0 %float_1 + %3767 = OpFSub %float %float_1 %5235 + %3768 = OpExtInst %float %1 FMin %5193 %3767 + %3770 = OpFMul %float %3768 %5418 + %5595 = OpExtInst %float %1 FClamp %3770 %float_0 %float_1 + %3791 = OpFSub %float %float_1 %5319 + %3792 = OpExtInst %float %1 FMin %5277 %3791 + %3794 = OpFMul %float %3792 %5451 + %5646 = OpExtInst %float %1 FClamp %3794 %float_0 %float_1 + %5692 = OpBitcast %uint %5493 + %5694 = OpShiftRightLogical %uint %5692 %uint_1 + %5696 = OpIAdd %uint %5694 %uint_532432441 + %5697 = OpBitcast %float %5696 + %5743 = OpBitcast %uint %5544 + %5745 = OpShiftRightLogical %uint %5743 %uint_1 + %5747 = OpIAdd %uint %5745 %uint_532432441 + %5748 = OpBitcast %float %5747 + %5794 = OpBitcast %uint %5595 + %5796 = OpShiftRightLogical %uint %5794 %uint_1 + %5798 = OpIAdd %uint %5796 %uint_532432441 + %5799 = OpBitcast %float %5798 + %5845 = OpBitcast %uint %5646 + %5847 = OpShiftRightLogical %uint %5845 %uint_1 + %5849 = OpIAdd %uint %5847 %uint_532432441 + %5850 = OpBitcast %float %5849 + %3830 = OpBitcast %float %2223 + %3836 = OpFMul %float %5697 %3830 + %3845 = OpFMul %float %5748 %3830 + %3854 = OpFMul %float %5799 %3830 + %3863 = OpFMul %float %5850 %3830 + %3869 = OpCompositeExtract %float %3138 0 + %3870 = OpFSub %float %float_1 %3869 + %3873 = OpCompositeExtract %float %3138 1 + %3874 = OpFSub %float %float_1 %3873 + %3875 = OpFMul %float %3870 %3874 + %3882 = OpFMul %float %3869 %3874 + %3889 = OpFMul %float %3870 %3873 + %3894 = OpFMul %float %3869 %3873 + %3898 = OpFSub %float %5067 %5025 + %3899 = OpFAdd %float %float_0_03125 %3898 + %5891 = OpBitcast %uint %3899 + %5892 = OpISub %uint %uint_2129690299 %5891 + %5893 = OpBitcast %float %5892 + %3902 = OpFMul %float %3875 %5893 + %3906 = OpFSub %float %5151 %5109 + %3907 = OpFAdd %float %float_0_03125 %3906 + %5902 = OpBitcast %uint %3907 + %5903 = OpISub %uint %uint_2129690299 %5902 + %5904 = OpBitcast %float %5903 + %3910 = OpFMul %float %3882 %5904 + %3914 = OpFSub %float %5235 %5193 + %3915 = OpFAdd %float %float_0_03125 %3914 + %5913 = OpBitcast %uint %3915 + %5914 = OpISub %uint %uint_2129690299 %5913 + %5915 = OpBitcast %float %5914 + %3918 = OpFMul %float %3889 %5915 + %3922 = OpFSub %float %5319 %5277 + %3923 = OpFAdd %float %float_0_03125 %3922 + %5924 = OpBitcast %uint %3923 + %5925 = OpISub %uint %uint_2129690299 %5924 + %5926 = OpBitcast %float %5925 + %3926 = OpFMul %float %3894 %5926 + %3932 = OpFMul %float %3836 %3902 + %3941 = OpFMul %float %3845 %3910 + %3959 = OpFMul %float %3854 %3918 + %3960 = OpFAdd %float %3941 %3959 + %3962 = OpFAdd %float %3960 %3902 + %3986 = OpFMul %float %3863 %3926 + %3987 = OpFAdd %float %3932 %3986 + %3989 = OpFAdd %float %3987 %3910 + %4016 = OpFAdd %float %3987 %3918 + %4043 = OpFAdd %float %3960 %3926 + %6451 = OpFAdd %float %3932 %3941 + %6452 = OpFAdd %float %6451 %3959 + %6453 = OpFAdd %float %6452 %3986 + %4085 = OpFMul %float %float_2 %6453 + %4087 = OpFAdd %float %4085 %3962 + %4089 = OpFAdd %float %4087 %3989 + %4091 = OpFAdd %float %4089 %4016 + %4093 = OpFAdd %float %4091 %4043 + %5949 = OpBitcast %uint %4093 + %5950 = OpISub %uint %uint_2129764351 %5949 + %5951 = OpBitcast %float %5950 + %5954 = OpFNegate %float %5951 + %5956 = OpFMul %float %5954 %4093 + %5958 = OpFAdd %float %5956 %float_2 + %5959 = OpFMul %float %5951 %5958 + %6454 = OpFAdd %float %4851 %4881 + %4103 = OpFMul %float %3932 %6454 + %4107 = OpFMul %float %4861 %3941 + %4108 = OpFAdd %float %4103 %4107 + %4112 = OpFMul %float %4911 %3941 + %4113 = OpFAdd %float %4108 %4112 + %4117 = OpFMul %float %4921 %3959 + %4118 = OpFAdd %float %4113 %4117 + %4122 = OpFMul %float %4971 %3959 + %4123 = OpFAdd %float %4118 %4122 + %4127 = OpFMul %float %4951 %3986 + %4128 = OpFAdd %float %4123 %4127 + %4132 = OpFMul %float %4981 %3986 + %4133 = OpFAdd %float %4128 %4132 + %4137 = OpFMul %float %4891 %3962 + %4138 = OpFAdd %float %4133 %4137 + %4142 = OpFMul %float %4901 %3989 + %4143 = OpFAdd %float %4138 %4142 + %4147 = OpFMul %float %4931 %4016 + %4148 = OpFAdd %float %4143 %4147 + %4152 = OpFMul %float %4941 %4043 + %4153 = OpFAdd %float %4148 %4152 + %4155 = OpFMul %float %4153 %5959 + %5973 = OpExtInst %float %1 FClamp %4155 %float_0 %float_1 + %6455 = OpFAdd %float %4854 %4884 + %4165 = OpFMul %float %3932 %6455 + %4169 = OpFMul %float %4864 %3941 + %4170 = OpFAdd %float %4165 %4169 + %4174 = OpFMul %float %4914 %3941 + %4175 = OpFAdd %float %4170 %4174 + %4179 = OpFMul %float %4924 %3959 + %4180 = OpFAdd %float %4175 %4179 + %4184 = OpFMul %float %4974 %3959 + %4185 = OpFAdd %float %4180 %4184 + %4189 = OpFMul %float %4954 %3986 + %4190 = OpFAdd %float %4185 %4189 + %4194 = OpFMul %float %4984 %3986 + %4195 = OpFAdd %float %4190 %4194 + %4199 = OpFMul %float %4894 %3962 + %4200 = OpFAdd %float %4195 %4199 + %4204 = OpFMul %float %4904 %3989 + %4205 = OpFAdd %float %4200 %4204 + %4209 = OpFMul %float %4934 %4016 + %4210 = OpFAdd %float %4205 %4209 + %4214 = OpFMul %float %4944 %4043 + %4215 = OpFAdd %float %4210 %4214 + %4217 = OpFMul %float %4215 %5959 + %5987 = OpExtInst %float %1 FClamp %4217 %float_0 %float_1 + %6456 = OpFAdd %float %4857 %4887 + %4227 = OpFMul %float %3932 %6456 + %4231 = OpFMul %float %4867 %3941 + %4232 = OpFAdd %float %4227 %4231 + %4236 = OpFMul %float %4917 %3941 + %4237 = OpFAdd %float %4232 %4236 + %4241 = OpFMul %float %4927 %3959 + %4242 = OpFAdd %float %4237 %4241 + %4246 = OpFMul %float %4977 %3959 + %4247 = OpFAdd %float %4242 %4246 + %4251 = OpFMul %float %4957 %3986 + %4252 = OpFAdd %float %4247 %4251 + %4256 = OpFMul %float %4987 %3986 + %4257 = OpFAdd %float %4252 %4256 + %4261 = OpFMul %float %4897 %3962 + %4262 = OpFAdd %float %4257 %4261 + %4266 = OpFMul %float %4907 %3989 + %4267 = OpFAdd %float %4262 %4266 + %4271 = OpFMul %float %4937 %4016 + %4272 = OpFAdd %float %4267 %4271 + %4276 = OpFMul %float %4947 %4043 + %4277 = OpFAdd %float %4272 %4276 + %4279 = OpFMul %float %4277 %5959 + %6001 = OpExtInst %float %1 FClamp %4279 %float_0 %float_1 + %2247 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %2247 %5973 + %2249 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %2249 %5987 + %2251 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %2251 %6001 + %2252 = OpLoad %v4float %xe_frag_color + %2253 = OpVectorShuffle %v3float %2252 %2252 0 1 2 + %2254 = OpExtInst %v3float %1 Sqrt %2253 + %2256 = OpCompositeExtract %float %2254 0 + OpStore %2247 %2256 + %2258 = OpCompositeExtract %float %2254 1 + OpStore %2249 %2258 + %2260 = OpCompositeExtract %float %2254 2 + OpStore %2251 %2260 + %2262 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %2262 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h new file mode 100644 index 000000000..da16935e6 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h @@ -0,0 +1,1341 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_fsr_easu.frag +const uint8_t guest_output_ffx_fsr_easu_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x5E, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0xBC, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, + 0xDE, 0x04, 0x00, 0x00, 0x58, 0x65, 0x46, 0x73, 0x72, 0x45, 0x61, 0x73, + 0x75, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, + 0x06, 0x00, 0x0C, 0x00, 0xDE, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x73, 0x72, 0x5F, 0x65, 0x61, 0x73, 0x75, 0x5F, + 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x00, + 0x06, 0x00, 0x0A, 0x00, 0xDE, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x73, 0x72, 0x5F, 0x65, 0x61, 0x73, 0x75, 0x5F, + 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, + 0x6E, 0x76, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xE0, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x08, 0x05, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0A, 0x05, 0x00, 0x00, + 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6F, 0x6F, 0x72, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xDE, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xDE, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xDE, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x08, 0x05, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x0A, 0x05, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x02, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0x74, 0x7D, 0x34, 0x5F, 0x2B, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0xB9, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x03, 0x00, 0xBA, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBA, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0xBF, 0x00, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0x3E, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBF, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xC8, 0x3F, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0xBF, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0x2B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x5D, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x61, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE6, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2F, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xBF, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x39, 0x03, 0x00, 0x00, 0xE1, 0x7A, 0x94, 0xBE, 0x2C, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x8D, 0x03, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xA8, 0x03, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xC3, 0x03, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xDE, 0x03, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x14, 0x04, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2F, 0x04, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x4B, 0x04, 0x00, 0x00, + 0x4A, 0x04, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x66, 0x04, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x81, 0x04, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x9C, 0x04, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xB7, 0x04, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x4A, 0x04, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0xDE, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xDF, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDE, 0x04, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xDF, 0x04, 0x00, 0x00, 0xE0, 0x04, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xE1, 0x04, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x07, 0x00, + 0x16, 0x00, 0x00, 0x00, 0xF1, 0x04, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00, 0xF8, 0x04, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x4A, 0x04, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x04, 0x00, + 0x01, 0x05, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x07, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x07, 0x05, 0x00, 0x00, + 0x08, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x09, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x09, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1A, 0x05, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x39, 0x12, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, 0x2C, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x3A, 0x12, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xE1, 0x04, 0x00, 0x00, 0xE2, 0x04, 0x00, 0x00, + 0xE0, 0x04, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE3, 0x04, 0x00, 0x00, 0xE2, 0x04, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, 0xE4, 0x04, 0x00, 0x00, + 0xE3, 0x04, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xE7, 0x04, 0x00, 0x00, 0xE3, 0x04, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE9, 0x04, 0x00, 0x00, + 0xE7, 0x04, 0x00, 0x00, 0x39, 0x12, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xEA, 0x04, 0x00, 0x00, 0xE9, 0x04, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xE1, 0x04, 0x00, 0x00, 0xF2, 0x04, 0x00, 0x00, + 0xE0, 0x04, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xF3, 0x04, 0x00, 0x00, 0xF2, 0x04, 0x00, 0x00, + 0x4F, 0x00, 0x09, 0x00, 0x16, 0x00, 0x00, 0x00, 0xF4, 0x04, 0x00, 0x00, + 0xF3, 0x04, 0x00, 0x00, 0xF3, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0xF5, 0x04, 0x00, 0x00, + 0xF1, 0x04, 0x00, 0x00, 0xF4, 0x04, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x62, 0x00, 0x00, 0x00, 0xF6, 0x04, 0x00, 0x00, 0xF5, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0xFC, 0x04, 0x00, 0x00, + 0xF8, 0x04, 0x00, 0x00, 0xF4, 0x04, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x62, 0x00, 0x00, 0x00, 0xFD, 0x04, 0x00, 0x00, 0xFC, 0x04, 0x00, 0x00, + 0x41, 0x00, 0x06, 0x00, 0x01, 0x05, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xE0, 0x04, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, + 0x04, 0x05, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x0B, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x05, 0x00, 0x00, 0x0B, 0x05, 0x00, 0x00, + 0x0B, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x6D, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0D, 0x05, 0x00, 0x00, + 0x0C, 0x05, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x13, 0x06, 0x00, 0x00, 0x0D, 0x05, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x19, 0x06, 0x00, 0x00, 0xE4, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1A, 0x06, 0x00, 0x00, + 0x13, 0x06, 0x00, 0x00, 0x19, 0x06, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0xEA, 0x04, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x21, 0x06, 0x00, 0x00, + 0x1A, 0x06, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x23, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x21, 0x06, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x21, 0x06, 0x00, 0x00, + 0x23, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x2A, 0x06, 0x00, 0x00, 0xF6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x2B, 0x06, 0x00, 0x00, + 0xF6, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x2C, 0x06, 0x00, 0x00, 0x2A, 0x06, 0x00, 0x00, + 0x2B, 0x06, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2D, 0x06, 0x00, 0x00, 0x2C, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x2E, 0x06, 0x00, 0x00, 0x23, 0x06, 0x00, 0x00, + 0x2D, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x31, 0x06, 0x00, 0x00, 0xF6, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x32, 0x06, 0x00, 0x00, + 0xF6, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x33, 0x06, 0x00, 0x00, 0x31, 0x06, 0x00, 0x00, + 0x32, 0x06, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x34, 0x06, 0x00, 0x00, 0x33, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, 0x2E, 0x06, 0x00, 0x00, + 0x34, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x39, 0x06, 0x00, 0x00, 0xFD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x3A, 0x06, 0x00, 0x00, + 0xFD, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x3B, 0x06, 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, + 0x3A, 0x06, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x3C, 0x06, 0x00, 0x00, 0x3B, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x06, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, + 0x3C, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x41, 0x06, 0x00, 0x00, 0xFD, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x42, 0x06, 0x00, 0x00, + 0xFD, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x43, 0x06, 0x00, 0x00, 0x41, 0x06, 0x00, 0x00, + 0x42, 0x06, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x44, 0x06, 0x00, 0x00, 0x43, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x45, 0x06, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, + 0x44, 0x06, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x4B, 0x06, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x4C, 0x06, 0x00, 0x00, + 0x4B, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x4D, 0x06, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, 0x4C, 0x06, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xBA, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x42, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x47, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x4C, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x51, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x3D, 0x06, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x56, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x3D, 0x06, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x5B, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x3D, 0x06, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x60, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x45, 0x06, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x65, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x45, 0x06, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x6A, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x45, 0x06, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x6F, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x4D, 0x06, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x74, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x4D, 0x06, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x79, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x4D, 0x06, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x68, 0x06, 0x00, 0x00, 0x4C, 0x08, 0x00, 0x00, 0x3A, 0x12, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x6B, 0x06, 0x00, 0x00, + 0x42, 0x08, 0x00, 0x00, 0x3A, 0x12, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x6D, 0x06, 0x00, 0x00, 0x6B, 0x06, 0x00, 0x00, + 0x47, 0x08, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x6E, 0x06, 0x00, 0x00, 0x68, 0x06, 0x00, 0x00, 0x6D, 0x06, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x71, 0x06, 0x00, 0x00, + 0x5B, 0x08, 0x00, 0x00, 0x3A, 0x12, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x74, 0x06, 0x00, 0x00, 0x51, 0x08, 0x00, 0x00, + 0x3A, 0x12, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x76, 0x06, 0x00, 0x00, 0x74, 0x06, 0x00, 0x00, 0x56, 0x08, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x77, 0x06, 0x00, 0x00, + 0x71, 0x06, 0x00, 0x00, 0x76, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x7A, 0x06, 0x00, 0x00, 0x6A, 0x08, 0x00, 0x00, + 0x3A, 0x12, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x7D, 0x06, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x3A, 0x12, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x7F, 0x06, 0x00, 0x00, + 0x7D, 0x06, 0x00, 0x00, 0x65, 0x08, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x80, 0x06, 0x00, 0x00, 0x7A, 0x06, 0x00, 0x00, + 0x7F, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x83, 0x06, 0x00, 0x00, 0x79, 0x08, 0x00, 0x00, 0x3A, 0x12, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x86, 0x06, 0x00, 0x00, + 0x6F, 0x08, 0x00, 0x00, 0x3A, 0x12, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x88, 0x06, 0x00, 0x00, 0x86, 0x06, 0x00, 0x00, + 0x74, 0x08, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x89, 0x06, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x88, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8B, 0x06, 0x00, 0x00, + 0x6E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8D, 0x06, 0x00, 0x00, 0x6E, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8F, 0x06, 0x00, 0x00, 0x77, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x91, 0x06, 0x00, 0x00, + 0x77, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x93, 0x06, 0x00, 0x00, 0x77, 0x06, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x95, 0x06, 0x00, 0x00, 0x77, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x80, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x99, 0x06, 0x00, 0x00, 0x80, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9B, 0x06, 0x00, 0x00, 0x80, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9D, 0x06, 0x00, 0x00, + 0x80, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9F, 0x06, 0x00, 0x00, 0x89, 0x06, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA1, 0x06, 0x00, 0x00, 0x89, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD2, 0x08, 0x00, 0x00, + 0x26, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD3, 0x08, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0xD2, 0x08, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD6, 0x08, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD7, 0x08, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0xD6, 0x08, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD8, 0x08, 0x00, 0x00, 0xD3, 0x08, 0x00, 0x00, + 0xD7, 0x08, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF8, 0x08, 0x00, 0x00, 0x9D, 0x06, 0x00, 0x00, 0x93, 0x06, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFB, 0x08, 0x00, 0x00, + 0x93, 0x06, 0x00, 0x00, 0x95, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFD, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xF8, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFF, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xFB, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xFD, 0x08, 0x00, 0x00, 0xFF, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x52, 0x09, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x53, 0x09, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x52, 0x09, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x09, 0x00, 0x00, + 0x53, 0x09, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x05, 0x09, 0x00, 0x00, 0x9D, 0x06, 0x00, 0x00, 0x95, 0x06, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, + 0x05, 0x09, 0x00, 0x00, 0xD8, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0x0E, 0x09, 0x00, 0x00, + 0x54, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5F, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x10, 0x09, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x00, + 0x5F, 0x09, 0x00, 0x00, 0x5F, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x17, 0x09, 0x00, 0x00, 0x14, 0x09, 0x00, 0x00, + 0xD8, 0x08, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1C, 0x09, 0x00, 0x00, 0x91, 0x06, 0x00, 0x00, 0x93, 0x06, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x09, 0x00, 0x00, + 0x93, 0x06, 0x00, 0x00, 0x8B, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x21, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x1C, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x23, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x1F, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x24, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x21, 0x09, 0x00, 0x00, 0x23, 0x09, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x6B, 0x09, 0x00, 0x00, + 0x24, 0x09, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x6C, 0x09, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x6B, 0x09, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x09, 0x00, 0x00, + 0x6C, 0x09, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x29, 0x09, 0x00, 0x00, 0x91, 0x06, 0x00, 0x00, 0x8B, 0x06, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2C, 0x09, 0x00, 0x00, + 0x29, 0x09, 0x00, 0x00, 0xD8, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x32, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x29, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x34, 0x09, 0x00, 0x00, 0x32, 0x09, 0x00, 0x00, + 0x6D, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x78, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x34, 0x09, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x09, 0x00, 0x00, + 0x78, 0x09, 0x00, 0x00, 0x78, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3B, 0x09, 0x00, 0x00, 0x38, 0x09, 0x00, 0x00, + 0xD8, 0x08, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3D, 0x09, 0x00, 0x00, 0x17, 0x09, 0x00, 0x00, 0x3B, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA7, 0x09, 0x00, 0x00, + 0xD2, 0x08, 0x00, 0x00, 0xD7, 0x08, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBD, 0x09, 0x00, 0x00, 0x9B, 0x06, 0x00, 0x00, + 0x9D, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC2, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xBD, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC5, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xC2, 0x09, 0x00, 0x00, 0xFD, 0x08, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x17, 0x0A, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x18, 0x0A, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x17, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x19, 0x0A, 0x00, 0x00, 0x18, 0x0A, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCA, 0x09, 0x00, 0x00, + 0x9B, 0x06, 0x00, 0x00, 0x93, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCD, 0x09, 0x00, 0x00, 0xCA, 0x09, 0x00, 0x00, + 0xA7, 0x09, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0xCD, 0x09, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD3, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xCA, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD5, 0x09, 0x00, 0x00, + 0xD3, 0x09, 0x00, 0x00, 0x19, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x24, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xD5, 0x09, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD9, 0x09, 0x00, 0x00, 0x24, 0x0A, 0x00, 0x00, 0x24, 0x0A, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDC, 0x09, 0x00, 0x00, + 0xD9, 0x09, 0x00, 0x00, 0xA7, 0x09, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDE, 0x09, 0x00, 0x00, 0x3D, 0x09, 0x00, 0x00, + 0xDC, 0x09, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE1, 0x09, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, 0x9D, 0x06, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, + 0x9D, 0x06, 0x00, 0x00, 0x8D, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE6, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE8, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE9, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE6, 0x09, 0x00, 0x00, 0xE8, 0x09, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x30, 0x0A, 0x00, 0x00, + 0xE9, 0x09, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x31, 0x0A, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x30, 0x0A, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x0A, 0x00, 0x00, + 0x31, 0x0A, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEE, 0x09, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, 0x8D, 0x06, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF1, 0x09, 0x00, 0x00, + 0xEE, 0x09, 0x00, 0x00, 0xA7, 0x09, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF4, 0x09, 0x00, 0x00, 0x2C, 0x09, 0x00, 0x00, + 0xF1, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF7, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xEE, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF9, 0x09, 0x00, 0x00, 0xF7, 0x09, 0x00, 0x00, 0x32, 0x0A, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3D, 0x0A, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xF9, 0x09, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFD, 0x09, 0x00, 0x00, 0x3D, 0x0A, 0x00, 0x00, + 0x3D, 0x0A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x0A, 0x00, 0x00, 0xFD, 0x09, 0x00, 0x00, 0xA7, 0x09, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x00, + 0xDE, 0x09, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x76, 0x0A, 0x00, 0x00, 0xD3, 0x08, 0x00, 0x00, + 0xD6, 0x08, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x82, 0x0A, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, 0x91, 0x06, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x85, 0x0A, 0x00, 0x00, + 0x91, 0x06, 0x00, 0x00, 0x8F, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x87, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x82, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x89, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x85, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8A, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x87, 0x0A, 0x00, 0x00, 0x89, 0x0A, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xDC, 0x0A, 0x00, 0x00, + 0x8A, 0x0A, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xDD, 0x0A, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0xDC, 0x0A, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDE, 0x0A, 0x00, 0x00, + 0xDD, 0x0A, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8F, 0x0A, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, 0x8F, 0x06, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x92, 0x0A, 0x00, 0x00, + 0x8F, 0x0A, 0x00, 0x00, 0x76, 0x0A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x95, 0x0A, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, + 0x92, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x98, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x8F, 0x0A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9A, 0x0A, 0x00, 0x00, 0x98, 0x0A, 0x00, 0x00, 0xDE, 0x0A, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE9, 0x0A, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x9A, 0x0A, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9E, 0x0A, 0x00, 0x00, 0xE9, 0x0A, 0x00, 0x00, + 0xE9, 0x0A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA1, 0x0A, 0x00, 0x00, 0x9E, 0x0A, 0x00, 0x00, 0x76, 0x0A, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA3, 0x0A, 0x00, 0x00, + 0x02, 0x0A, 0x00, 0x00, 0xA1, 0x0A, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA6, 0x0A, 0x00, 0x00, 0xA1, 0x06, 0x00, 0x00, + 0x91, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAB, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xA6, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAE, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xAB, 0x0A, 0x00, 0x00, 0x21, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xF5, 0x0A, 0x00, 0x00, 0xAE, 0x0A, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xF6, 0x0A, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xF5, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF7, 0x0A, 0x00, 0x00, 0xF6, 0x0A, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB3, 0x0A, 0x00, 0x00, + 0xA1, 0x06, 0x00, 0x00, 0x93, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB6, 0x0A, 0x00, 0x00, 0xB3, 0x0A, 0x00, 0x00, + 0x76, 0x0A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB9, 0x0A, 0x00, 0x00, 0xF4, 0x09, 0x00, 0x00, 0xB6, 0x0A, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBC, 0x0A, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB3, 0x0A, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBE, 0x0A, 0x00, 0x00, + 0xBC, 0x0A, 0x00, 0x00, 0xF7, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xBE, 0x0A, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC2, 0x0A, 0x00, 0x00, 0x02, 0x0B, 0x00, 0x00, 0x02, 0x0B, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC5, 0x0A, 0x00, 0x00, + 0xC2, 0x0A, 0x00, 0x00, 0x76, 0x0A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC7, 0x0A, 0x00, 0x00, 0xA3, 0x0A, 0x00, 0x00, + 0xC5, 0x0A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x43, 0x0B, 0x00, 0x00, 0xD2, 0x08, 0x00, 0x00, 0xD6, 0x08, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x47, 0x0B, 0x00, 0x00, + 0x99, 0x06, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4C, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x0B, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4F, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x4C, 0x0B, 0x00, 0x00, 0x87, 0x0A, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xA1, 0x0B, 0x00, 0x00, + 0x4F, 0x0B, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xA2, 0x0B, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0xA1, 0x0B, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA3, 0x0B, 0x00, 0x00, + 0xA2, 0x0B, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x54, 0x0B, 0x00, 0x00, 0x99, 0x06, 0x00, 0x00, 0x91, 0x06, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x57, 0x0B, 0x00, 0x00, + 0x54, 0x0B, 0x00, 0x00, 0x43, 0x0B, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5A, 0x0B, 0x00, 0x00, 0x95, 0x0A, 0x00, 0x00, + 0x57, 0x0B, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2E, 0x11, 0x00, 0x00, 0x5A, 0x0B, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5D, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x54, 0x0B, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5F, 0x0B, 0x00, 0x00, 0x5D, 0x0B, 0x00, 0x00, 0xA3, 0x0B, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAE, 0x0B, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x5F, 0x0B, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x63, 0x0B, 0x00, 0x00, 0xAE, 0x0B, 0x00, 0x00, + 0xAE, 0x0B, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x66, 0x0B, 0x00, 0x00, 0x63, 0x0B, 0x00, 0x00, 0x43, 0x0B, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x68, 0x0B, 0x00, 0x00, + 0xC7, 0x0A, 0x00, 0x00, 0x66, 0x0B, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6B, 0x0B, 0x00, 0x00, 0x9F, 0x06, 0x00, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x70, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x6B, 0x0B, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x73, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x70, 0x0B, 0x00, 0x00, 0xE6, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xBA, 0x0B, 0x00, 0x00, 0x73, 0x0B, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xBB, 0x0B, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xBA, 0x0B, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBC, 0x0B, 0x00, 0x00, 0xBB, 0x0B, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x0B, 0x00, 0x00, + 0x9F, 0x06, 0x00, 0x00, 0x9D, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7B, 0x0B, 0x00, 0x00, 0x78, 0x0B, 0x00, 0x00, + 0x43, 0x0B, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7E, 0x0B, 0x00, 0x00, 0xB9, 0x0A, 0x00, 0x00, 0x7B, 0x0B, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x31, 0x11, 0x00, 0x00, + 0x7E, 0x0B, 0x00, 0x00, 0x2E, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x81, 0x0B, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x78, 0x0B, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x83, 0x0B, 0x00, 0x00, + 0x81, 0x0B, 0x00, 0x00, 0xBC, 0x0B, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC7, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x83, 0x0B, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x87, 0x0B, 0x00, 0x00, 0xC7, 0x0B, 0x00, 0x00, 0xC7, 0x0B, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8A, 0x0B, 0x00, 0x00, + 0x87, 0x0B, 0x00, 0x00, 0x43, 0x0B, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8C, 0x0B, 0x00, 0x00, 0x68, 0x0B, 0x00, 0x00, + 0x8A, 0x0B, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xD2, 0x06, 0x00, 0x00, 0x31, 0x11, 0x00, 0x00, 0x31, 0x11, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD4, 0x06, 0x00, 0x00, + 0xD2, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD6, 0x06, 0x00, 0x00, 0xD2, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD7, 0x06, 0x00, 0x00, 0xD4, 0x06, 0x00, 0x00, 0xD6, 0x06, 0x00, 0x00, + 0xB8, 0x00, 0x05, 0x00, 0x4F, 0x00, 0x00, 0x00, 0xDA, 0x06, 0x00, 0x00, + 0xD7, 0x06, 0x00, 0x00, 0xE6, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xD7, 0x0B, 0x00, 0x00, 0xD7, 0x06, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xD9, 0x0B, 0x00, 0x00, + 0xD7, 0x0B, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xDA, 0x0B, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, + 0xD9, 0x0B, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDB, 0x0B, 0x00, 0x00, 0xDA, 0x0B, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, + 0xE2, 0x06, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xE2, 0x06, 0x00, 0x00, + 0xA9, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5C, 0x12, 0x00, 0x00, + 0xDA, 0x06, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0xDB, 0x0B, 0x00, 0x00, + 0xF7, 0x00, 0x03, 0x00, 0xEA, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x04, 0x00, 0xDA, 0x06, 0x00, 0x00, 0xE5, 0x06, 0x00, 0x00, + 0xE7, 0x06, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xE7, 0x06, 0x00, 0x00, + 0xF9, 0x00, 0x02, 0x00, 0xEA, 0x06, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0xE5, 0x06, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xEA, 0x06, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0xEA, 0x06, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3E, 0x12, 0x00, 0x00, 0x5A, 0x0B, 0x00, 0x00, + 0xE7, 0x06, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0xE5, 0x06, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, + 0x3E, 0x12, 0x00, 0x00, 0x31, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xEC, 0x0B, 0x00, 0x00, + 0x5C, 0x12, 0x00, 0x00, 0x5C, 0x12, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xF0, 0x06, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, + 0xEC, 0x0B, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF3, 0x06, 0x00, 0x00, 0x8C, 0x0B, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF6, 0x06, 0x00, 0x00, + 0xF3, 0x06, 0x00, 0x00, 0xF3, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0xF0, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFB, 0x06, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, + 0xF0, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, + 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x01, 0x07, 0x00, 0x00, 0xFB, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, + 0x07, 0x07, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xF5, 0x0B, 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xF6, 0x0B, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xF5, 0x0B, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF7, 0x0B, 0x00, 0x00, 0xF6, 0x0B, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, + 0xF7, 0x0B, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0E, 0x07, 0x00, 0x00, 0x0A, 0x07, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x07, 0x00, 0x00, + 0x0E, 0x07, 0x00, 0x00, 0xF6, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x11, 0x07, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x10, 0x07, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x15, 0x07, 0x00, 0x00, 0x2F, 0x03, 0x00, 0x00, 0xF6, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x07, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x15, 0x07, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, 0x11, 0x07, 0x00, 0x00, + 0x16, 0x07, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1B, 0x07, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0xF6, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, 0x1B, 0x07, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x12, 0x0C, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x13, 0x0C, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x12, 0x0C, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, 0x13, 0x0C, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, + 0x51, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x22, 0x07, 0x00, 0x00, 0x56, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x24, 0x07, 0x00, 0x00, 0x5B, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0x25, 0x07, 0x00, 0x00, + 0x20, 0x07, 0x00, 0x00, 0x22, 0x07, 0x00, 0x00, 0x24, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x07, 0x00, 0x00, + 0x60, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x29, 0x07, 0x00, 0x00, 0x65, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2B, 0x07, 0x00, 0x00, 0x6A, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0x2C, 0x07, 0x00, 0x00, + 0x27, 0x07, 0x00, 0x00, 0x29, 0x07, 0x00, 0x00, 0x2B, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2E, 0x07, 0x00, 0x00, + 0x51, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00, 0x56, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x32, 0x07, 0x00, 0x00, 0x5B, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0x33, 0x07, 0x00, 0x00, + 0x2E, 0x07, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00, 0x32, 0x07, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1D, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x2C, 0x07, 0x00, 0x00, + 0x33, 0x07, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x1E, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x25, 0x07, 0x00, 0x00, 0x1D, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x38, 0x07, 0x00, 0x00, 0x65, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3A, 0x07, 0x00, 0x00, + 0x6A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x3B, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, + 0x38, 0x07, 0x00, 0x00, 0x3A, 0x07, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x3C, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x1E, 0x0C, 0x00, 0x00, 0x3B, 0x07, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x24, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2C, 0x07, 0x00, 0x00, + 0x33, 0x07, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x25, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x25, 0x07, 0x00, 0x00, 0x24, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x5A, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x25, 0x0C, 0x00, 0x00, 0x3B, 0x07, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x5E, 0x07, 0x00, 0x00, + 0x8D, 0x03, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x42, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x62, 0x07, 0x00, 0x00, 0x47, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, 0x07, 0x00, 0x00, + 0x4C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x65, 0x07, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, + 0x62, 0x07, 0x00, 0x00, 0x64, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3B, 0x0C, 0x00, 0x00, 0x5E, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3E, 0x0C, 0x00, 0x00, 0x3B, 0x0C, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0x5E, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x43, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x44, 0x0C, 0x00, 0x00, 0x3E, 0x0C, 0x00, 0x00, 0x43, 0x0C, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x5D, 0x11, 0x00, 0x00, + 0x44, 0x0C, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, + 0xFD, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x0C, 0x00, 0x00, 0x3B, 0x0C, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x0C, 0x00, 0x00, + 0x40, 0x0C, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, 0x4B, 0x0C, 0x00, 0x00, + 0x50, 0x0C, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x63, 0x11, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, 0x5D, 0x11, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x55, 0x0C, 0x00, 0x00, 0x63, 0x11, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x57, 0x0C, 0x00, 0x00, + 0x55, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5A, 0x0C, 0x00, 0x00, 0x57, 0x0C, 0x00, 0x00, + 0x57, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5C, 0x0C, 0x00, 0x00, 0x55, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5F, 0x0C, 0x00, 0x00, + 0x5C, 0x0C, 0x00, 0x00, 0x5C, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x60, 0x0C, 0x00, 0x00, 0x5A, 0x0C, 0x00, 0x00, + 0x5F, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x63, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x60, 0x0C, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x66, 0x0C, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x63, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x68, 0x0C, 0x00, 0x00, 0x66, 0x0C, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6B, 0x0C, 0x00, 0x00, + 0x1C, 0x07, 0x00, 0x00, 0x63, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6D, 0x0C, 0x00, 0x00, 0x6B, 0x0C, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x70, 0x0C, 0x00, 0x00, 0x68, 0x0C, 0x00, 0x00, 0x68, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x73, 0x0C, 0x00, 0x00, + 0x6D, 0x0C, 0x00, 0x00, 0x6D, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x70, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x78, 0x0C, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7B, 0x0C, 0x00, 0x00, + 0x78, 0x0C, 0x00, 0x00, 0x73, 0x0C, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x7E, 0x0C, 0x00, 0x00, 0x65, 0x07, 0x00, 0x00, + 0x7B, 0x0C, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x70, 0x07, 0x00, 0x00, 0xA8, 0x03, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x72, 0x07, 0x00, 0x00, + 0x42, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x74, 0x07, 0x00, 0x00, 0x47, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x76, 0x07, 0x00, 0x00, 0x4C, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0x77, 0x07, 0x00, 0x00, + 0x72, 0x07, 0x00, 0x00, 0x74, 0x07, 0x00, 0x00, 0x76, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9F, 0x0C, 0x00, 0x00, + 0x70, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA2, 0x0C, 0x00, 0x00, 0x9F, 0x0C, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA4, 0x0C, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA7, 0x0C, 0x00, 0x00, + 0xA4, 0x0C, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA8, 0x0C, 0x00, 0x00, 0xA2, 0x0C, 0x00, 0x00, + 0xA7, 0x0C, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x70, 0x11, 0x00, 0x00, 0xA8, 0x0C, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAF, 0x0C, 0x00, 0x00, 0x9F, 0x0C, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB4, 0x0C, 0x00, 0x00, + 0xA4, 0x0C, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB5, 0x0C, 0x00, 0x00, 0xAF, 0x0C, 0x00, 0x00, + 0xB4, 0x0C, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x76, 0x11, 0x00, 0x00, 0xB5, 0x0C, 0x00, 0x00, 0x70, 0x11, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xB9, 0x0C, 0x00, 0x00, 0x76, 0x11, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBB, 0x0C, 0x00, 0x00, + 0xB9, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBE, 0x0C, 0x00, 0x00, 0xBB, 0x0C, 0x00, 0x00, + 0xBB, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC0, 0x0C, 0x00, 0x00, 0xB9, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, + 0xC0, 0x0C, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC4, 0x0C, 0x00, 0x00, 0xBE, 0x0C, 0x00, 0x00, + 0xC3, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC7, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xC4, 0x0C, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCA, 0x0C, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xC7, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCC, 0x0C, 0x00, 0x00, 0xCA, 0x0C, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCF, 0x0C, 0x00, 0x00, + 0x1C, 0x07, 0x00, 0x00, 0xC7, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD1, 0x0C, 0x00, 0x00, 0xCF, 0x0C, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD4, 0x0C, 0x00, 0x00, 0xCC, 0x0C, 0x00, 0x00, 0xCC, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD7, 0x0C, 0x00, 0x00, + 0xD1, 0x0C, 0x00, 0x00, 0xD1, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDA, 0x0C, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0xD4, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDC, 0x0C, 0x00, 0x00, 0xDA, 0x0C, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDF, 0x0C, 0x00, 0x00, + 0xDC, 0x0C, 0x00, 0x00, 0xD7, 0x0C, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xE2, 0x0C, 0x00, 0x00, 0x77, 0x07, 0x00, 0x00, + 0xDF, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xE4, 0x0C, 0x00, 0x00, 0x7E, 0x0C, 0x00, 0x00, 0xE2, 0x0C, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE7, 0x0C, 0x00, 0x00, + 0x7B, 0x0C, 0x00, 0x00, 0xDF, 0x0C, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x82, 0x07, 0x00, 0x00, 0xC3, 0x03, 0x00, 0x00, + 0x26, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x84, 0x07, 0x00, 0x00, 0x51, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x86, 0x07, 0x00, 0x00, + 0x56, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x88, 0x07, 0x00, 0x00, 0x5B, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x89, 0x07, 0x00, 0x00, 0x84, 0x07, 0x00, 0x00, 0x86, 0x07, 0x00, 0x00, + 0x88, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x0D, 0x00, 0x00, 0x82, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x0D, 0x00, 0x00, + 0x03, 0x0D, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, 0x82, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0B, 0x0D, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x0D, 0x00, 0x00, + 0x06, 0x0D, 0x00, 0x00, 0x0B, 0x0D, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x83, 0x11, 0x00, 0x00, 0x0C, 0x0D, 0x00, 0x00, + 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x13, 0x0D, 0x00, 0x00, 0x03, 0x0D, 0x00, 0x00, + 0x4A, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x18, 0x0D, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x0D, 0x00, 0x00, + 0x13, 0x0D, 0x00, 0x00, 0x18, 0x0D, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x89, 0x11, 0x00, 0x00, 0x19, 0x0D, 0x00, 0x00, + 0x83, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x1D, 0x0D, 0x00, 0x00, 0x89, 0x11, 0x00, 0x00, + 0x17, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1F, 0x0D, 0x00, 0x00, 0x1D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x00, + 0x1F, 0x0D, 0x00, 0x00, 0x1F, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x24, 0x0D, 0x00, 0x00, 0x1D, 0x0D, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x27, 0x0D, 0x00, 0x00, 0x24, 0x0D, 0x00, 0x00, 0x24, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, 0x0D, 0x00, 0x00, + 0x22, 0x0D, 0x00, 0x00, 0x27, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x28, 0x0D, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2E, 0x0D, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x30, 0x0D, 0x00, 0x00, 0x2E, 0x0D, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x33, 0x0D, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x0D, 0x00, 0x00, + 0x33, 0x0D, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x38, 0x0D, 0x00, 0x00, 0x30, 0x0D, 0x00, 0x00, + 0x30, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3B, 0x0D, 0x00, 0x00, 0x35, 0x0D, 0x00, 0x00, 0x35, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3E, 0x0D, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0x38, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x40, 0x0D, 0x00, 0x00, 0x3E, 0x0D, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x43, 0x0D, 0x00, 0x00, 0x40, 0x0D, 0x00, 0x00, 0x3B, 0x0D, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x46, 0x0D, 0x00, 0x00, + 0x89, 0x07, 0x00, 0x00, 0x43, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x48, 0x0D, 0x00, 0x00, 0xE4, 0x0C, 0x00, 0x00, + 0x46, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x0D, 0x00, 0x00, 0xE7, 0x0C, 0x00, 0x00, 0x43, 0x0D, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x94, 0x07, 0x00, 0x00, + 0xDE, 0x03, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x67, 0x0D, 0x00, 0x00, 0x94, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6A, 0x0D, 0x00, 0x00, 0x67, 0x0D, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0x94, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6F, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x70, 0x0D, 0x00, 0x00, 0x6A, 0x0D, 0x00, 0x00, 0x6F, 0x0D, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x96, 0x11, 0x00, 0x00, + 0x70, 0x0D, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x0D, 0x00, 0x00, + 0x67, 0x0D, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7C, 0x0D, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7D, 0x0D, 0x00, 0x00, 0x77, 0x0D, 0x00, 0x00, 0x7C, 0x0D, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x9C, 0x11, 0x00, 0x00, + 0x7D, 0x0D, 0x00, 0x00, 0x96, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x81, 0x0D, 0x00, 0x00, + 0x9C, 0x11, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x83, 0x0D, 0x00, 0x00, 0x81, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x86, 0x0D, 0x00, 0x00, 0x83, 0x0D, 0x00, 0x00, 0x83, 0x0D, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x0D, 0x00, 0x00, + 0x81, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8B, 0x0D, 0x00, 0x00, 0x88, 0x0D, 0x00, 0x00, + 0x88, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8C, 0x0D, 0x00, 0x00, 0x86, 0x0D, 0x00, 0x00, 0x8B, 0x0D, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8F, 0x0D, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x8C, 0x0D, 0x00, 0x00, + 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x92, 0x0D, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x8F, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x94, 0x0D, 0x00, 0x00, + 0x92, 0x0D, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x97, 0x0D, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, + 0x8F, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x99, 0x0D, 0x00, 0x00, 0x97, 0x0D, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9C, 0x0D, 0x00, 0x00, + 0x94, 0x0D, 0x00, 0x00, 0x94, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9F, 0x0D, 0x00, 0x00, 0x99, 0x0D, 0x00, 0x00, + 0x99, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA2, 0x0D, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x9C, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA4, 0x0D, 0x00, 0x00, + 0xA2, 0x0D, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA7, 0x0D, 0x00, 0x00, 0xA4, 0x0D, 0x00, 0x00, + 0x9F, 0x0D, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xAA, 0x0D, 0x00, 0x00, 0x33, 0x07, 0x00, 0x00, 0xA7, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0xAC, 0x0D, 0x00, 0x00, + 0x48, 0x0D, 0x00, 0x00, 0xAA, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAF, 0x0D, 0x00, 0x00, 0x4B, 0x0D, 0x00, 0x00, + 0xA7, 0x0D, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xA6, 0x07, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCB, 0x0D, 0x00, 0x00, 0xA6, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCE, 0x0D, 0x00, 0x00, 0xCB, 0x0D, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD0, 0x0D, 0x00, 0x00, + 0xA6, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD3, 0x0D, 0x00, 0x00, 0xD0, 0x0D, 0x00, 0x00, + 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD4, 0x0D, 0x00, 0x00, 0xCE, 0x0D, 0x00, 0x00, 0xD3, 0x0D, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xA9, 0x11, 0x00, 0x00, + 0xD4, 0x0D, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDB, 0x0D, 0x00, 0x00, + 0xCB, 0x0D, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE0, 0x0D, 0x00, 0x00, 0xD0, 0x0D, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE1, 0x0D, 0x00, 0x00, 0xDB, 0x0D, 0x00, 0x00, 0xE0, 0x0D, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xAF, 0x11, 0x00, 0x00, + 0xE1, 0x0D, 0x00, 0x00, 0xA9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE5, 0x0D, 0x00, 0x00, + 0xAF, 0x11, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE7, 0x0D, 0x00, 0x00, 0xE5, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEA, 0x0D, 0x00, 0x00, 0xE7, 0x0D, 0x00, 0x00, 0xE7, 0x0D, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEC, 0x0D, 0x00, 0x00, + 0xE5, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, 0xEC, 0x0D, 0x00, 0x00, + 0xEC, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF0, 0x0D, 0x00, 0x00, 0xEA, 0x0D, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF3, 0x0D, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xF0, 0x0D, 0x00, 0x00, + 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF6, 0x0D, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xF3, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF8, 0x0D, 0x00, 0x00, + 0xF6, 0x0D, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFB, 0x0D, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, + 0xF3, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFD, 0x0D, 0x00, 0x00, 0xFB, 0x0D, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0xF8, 0x0D, 0x00, 0x00, 0xF8, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x00, 0x00, 0xFD, 0x0D, 0x00, 0x00, + 0xFD, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x0E, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00, 0x00, + 0x06, 0x0E, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0B, 0x0E, 0x00, 0x00, 0x08, 0x0E, 0x00, 0x00, + 0x03, 0x0E, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x0E, 0x0E, 0x00, 0x00, 0x25, 0x07, 0x00, 0x00, 0x0B, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0x00, + 0xAC, 0x0D, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x13, 0x0E, 0x00, 0x00, 0xAF, 0x0D, 0x00, 0x00, + 0x0B, 0x0E, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xB8, 0x07, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, + 0x51, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBC, 0x07, 0x00, 0x00, 0x56, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBE, 0x07, 0x00, 0x00, 0x5B, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0xBF, 0x07, 0x00, 0x00, + 0xBA, 0x07, 0x00, 0x00, 0xBC, 0x07, 0x00, 0x00, 0xBE, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2F, 0x0E, 0x00, 0x00, + 0xB8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x32, 0x0E, 0x00, 0x00, 0x2F, 0x0E, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x34, 0x0E, 0x00, 0x00, 0xB8, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x0E, 0x00, 0x00, + 0x34, 0x0E, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x38, 0x0E, 0x00, 0x00, 0x32, 0x0E, 0x00, 0x00, + 0x37, 0x0E, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xBC, 0x11, 0x00, 0x00, 0x38, 0x0E, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3F, 0x0E, 0x00, 0x00, 0x2F, 0x0E, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x0E, 0x00, 0x00, + 0x34, 0x0E, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x45, 0x0E, 0x00, 0x00, 0x3F, 0x0E, 0x00, 0x00, + 0x44, 0x0E, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xC2, 0x11, 0x00, 0x00, 0x45, 0x0E, 0x00, 0x00, 0xBC, 0x11, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x49, 0x0E, 0x00, 0x00, 0xC2, 0x11, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4B, 0x0E, 0x00, 0x00, + 0x49, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4E, 0x0E, 0x00, 0x00, 0x4B, 0x0E, 0x00, 0x00, + 0x4B, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x50, 0x0E, 0x00, 0x00, 0x49, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x0E, 0x00, 0x00, + 0x50, 0x0E, 0x00, 0x00, 0x50, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x54, 0x0E, 0x00, 0x00, 0x4E, 0x0E, 0x00, 0x00, + 0x53, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x57, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x54, 0x0E, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5A, 0x0E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x57, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5C, 0x0E, 0x00, 0x00, 0x5A, 0x0E, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5F, 0x0E, 0x00, 0x00, + 0x1C, 0x07, 0x00, 0x00, 0x57, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x00, 0x00, 0x5F, 0x0E, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x64, 0x0E, 0x00, 0x00, 0x5C, 0x0E, 0x00, 0x00, 0x5C, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x67, 0x0E, 0x00, 0x00, + 0x61, 0x0E, 0x00, 0x00, 0x61, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6A, 0x0E, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x64, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6C, 0x0E, 0x00, 0x00, 0x6A, 0x0E, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6F, 0x0E, 0x00, 0x00, + 0x6C, 0x0E, 0x00, 0x00, 0x67, 0x0E, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x72, 0x0E, 0x00, 0x00, 0xBF, 0x07, 0x00, 0x00, + 0x6F, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x74, 0x0E, 0x00, 0x00, 0x10, 0x0E, 0x00, 0x00, 0x72, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x0E, 0x00, 0x00, + 0x13, 0x0E, 0x00, 0x00, 0x6F, 0x0E, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xCA, 0x07, 0x00, 0x00, 0x2F, 0x04, 0x00, 0x00, + 0x26, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x93, 0x0E, 0x00, 0x00, 0xCA, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x96, 0x0E, 0x00, 0x00, + 0x93, 0x0E, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x98, 0x0E, 0x00, 0x00, 0xCA, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9B, 0x0E, 0x00, 0x00, 0x98, 0x0E, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9C, 0x0E, 0x00, 0x00, + 0x96, 0x0E, 0x00, 0x00, 0x9B, 0x0E, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xCF, 0x11, 0x00, 0x00, 0x9C, 0x0E, 0x00, 0x00, + 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA3, 0x0E, 0x00, 0x00, 0x93, 0x0E, 0x00, 0x00, + 0x4A, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA8, 0x0E, 0x00, 0x00, 0x98, 0x0E, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA9, 0x0E, 0x00, 0x00, + 0xA3, 0x0E, 0x00, 0x00, 0xA8, 0x0E, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xD5, 0x11, 0x00, 0x00, 0xA9, 0x0E, 0x00, 0x00, + 0xCF, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xAD, 0x0E, 0x00, 0x00, 0xD5, 0x11, 0x00, 0x00, + 0x17, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAF, 0x0E, 0x00, 0x00, 0xAD, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB2, 0x0E, 0x00, 0x00, + 0xAF, 0x0E, 0x00, 0x00, 0xAF, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB4, 0x0E, 0x00, 0x00, 0xAD, 0x0E, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB7, 0x0E, 0x00, 0x00, 0xB4, 0x0E, 0x00, 0x00, 0xB4, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB8, 0x0E, 0x00, 0x00, + 0xB2, 0x0E, 0x00, 0x00, 0xB7, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBB, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xB8, 0x0E, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBE, 0x0E, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xBB, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC0, 0x0E, 0x00, 0x00, 0xBE, 0x0E, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC3, 0x0E, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, 0xBB, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC5, 0x0E, 0x00, 0x00, + 0xC3, 0x0E, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC8, 0x0E, 0x00, 0x00, 0xC0, 0x0E, 0x00, 0x00, + 0xC0, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCB, 0x0E, 0x00, 0x00, 0xC5, 0x0E, 0x00, 0x00, 0xC5, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCE, 0x0E, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0xC8, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD0, 0x0E, 0x00, 0x00, 0xCE, 0x0E, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD3, 0x0E, 0x00, 0x00, 0xD0, 0x0E, 0x00, 0x00, 0xCB, 0x0E, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0xD6, 0x0E, 0x00, 0x00, + 0x3B, 0x07, 0x00, 0x00, 0xD3, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xD8, 0x0E, 0x00, 0x00, 0x74, 0x0E, 0x00, 0x00, + 0xD6, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDB, 0x0E, 0x00, 0x00, 0x77, 0x0E, 0x00, 0x00, 0xD3, 0x0E, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xDC, 0x07, 0x00, 0x00, + 0x4B, 0x04, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDE, 0x07, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE0, 0x07, 0x00, 0x00, 0x65, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE2, 0x07, 0x00, 0x00, + 0x6A, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xE3, 0x07, 0x00, 0x00, 0xDE, 0x07, 0x00, 0x00, + 0xE0, 0x07, 0x00, 0x00, 0xE2, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF7, 0x0E, 0x00, 0x00, 0xDC, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFA, 0x0E, 0x00, 0x00, 0xF7, 0x0E, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFC, 0x0E, 0x00, 0x00, + 0xDC, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFF, 0x0E, 0x00, 0x00, 0xFC, 0x0E, 0x00, 0x00, + 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0xFA, 0x0E, 0x00, 0x00, 0xFF, 0x0E, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE2, 0x11, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x00, 0x00, + 0xF7, 0x0E, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x00, 0x00, 0xFC, 0x0E, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0D, 0x0F, 0x00, 0x00, 0x07, 0x0F, 0x00, 0x00, 0x0C, 0x0F, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE8, 0x11, 0x00, 0x00, + 0x0D, 0x0F, 0x00, 0x00, 0xE2, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x11, 0x0F, 0x00, 0x00, + 0xE8, 0x11, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x13, 0x0F, 0x00, 0x00, 0x11, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x16, 0x0F, 0x00, 0x00, 0x13, 0x0F, 0x00, 0x00, 0x13, 0x0F, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x0F, 0x00, 0x00, + 0x11, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1B, 0x0F, 0x00, 0x00, 0x18, 0x0F, 0x00, 0x00, + 0x18, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1C, 0x0F, 0x00, 0x00, 0x16, 0x0F, 0x00, 0x00, 0x1B, 0x0F, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x1C, 0x0F, 0x00, 0x00, + 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x22, 0x0F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x24, 0x0F, 0x00, 0x00, + 0x22, 0x0F, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x27, 0x0F, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, + 0x1F, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x29, 0x0F, 0x00, 0x00, 0x27, 0x0F, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2C, 0x0F, 0x00, 0x00, + 0x24, 0x0F, 0x00, 0x00, 0x24, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2F, 0x0F, 0x00, 0x00, 0x29, 0x0F, 0x00, 0x00, + 0x29, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x32, 0x0F, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x2C, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x0F, 0x00, 0x00, + 0x32, 0x0F, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x37, 0x0F, 0x00, 0x00, 0x34, 0x0F, 0x00, 0x00, + 0x2F, 0x0F, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x3A, 0x0F, 0x00, 0x00, 0xE3, 0x07, 0x00, 0x00, 0x37, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3C, 0x0F, 0x00, 0x00, + 0xD8, 0x0E, 0x00, 0x00, 0x3A, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3F, 0x0F, 0x00, 0x00, 0xDB, 0x0E, 0x00, 0x00, + 0x37, 0x0F, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xEE, 0x07, 0x00, 0x00, 0x66, 0x04, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, + 0x60, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF2, 0x07, 0x00, 0x00, 0x65, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF4, 0x07, 0x00, 0x00, 0x6A, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0xF5, 0x07, 0x00, 0x00, + 0xF0, 0x07, 0x00, 0x00, 0xF2, 0x07, 0x00, 0x00, 0xF4, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5B, 0x0F, 0x00, 0x00, + 0xEE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5E, 0x0F, 0x00, 0x00, 0x5B, 0x0F, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x60, 0x0F, 0x00, 0x00, 0xEE, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x63, 0x0F, 0x00, 0x00, + 0x60, 0x0F, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x64, 0x0F, 0x00, 0x00, 0x5E, 0x0F, 0x00, 0x00, + 0x63, 0x0F, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xF5, 0x11, 0x00, 0x00, 0x64, 0x0F, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6B, 0x0F, 0x00, 0x00, 0x5B, 0x0F, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x70, 0x0F, 0x00, 0x00, + 0x60, 0x0F, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x71, 0x0F, 0x00, 0x00, 0x6B, 0x0F, 0x00, 0x00, + 0x70, 0x0F, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xFB, 0x11, 0x00, 0x00, 0x71, 0x0F, 0x00, 0x00, 0xF5, 0x11, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x75, 0x0F, 0x00, 0x00, 0xFB, 0x11, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x0F, 0x00, 0x00, + 0x75, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7A, 0x0F, 0x00, 0x00, 0x77, 0x0F, 0x00, 0x00, + 0x77, 0x0F, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7C, 0x0F, 0x00, 0x00, 0x75, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7F, 0x0F, 0x00, 0x00, + 0x7C, 0x0F, 0x00, 0x00, 0x7C, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x7A, 0x0F, 0x00, 0x00, + 0x7F, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x83, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x80, 0x0F, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x86, 0x0F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x83, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x88, 0x0F, 0x00, 0x00, 0x86, 0x0F, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8B, 0x0F, 0x00, 0x00, + 0x1C, 0x07, 0x00, 0x00, 0x83, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8D, 0x0F, 0x00, 0x00, 0x8B, 0x0F, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x90, 0x0F, 0x00, 0x00, 0x88, 0x0F, 0x00, 0x00, 0x88, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x0F, 0x00, 0x00, + 0x8D, 0x0F, 0x00, 0x00, 0x8D, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x96, 0x0F, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x90, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x98, 0x0F, 0x00, 0x00, 0x96, 0x0F, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9B, 0x0F, 0x00, 0x00, + 0x98, 0x0F, 0x00, 0x00, 0x93, 0x0F, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x9E, 0x0F, 0x00, 0x00, 0xF5, 0x07, 0x00, 0x00, + 0x9B, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xA0, 0x0F, 0x00, 0x00, 0x3C, 0x0F, 0x00, 0x00, 0x9E, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, + 0x3F, 0x0F, 0x00, 0x00, 0x9B, 0x0F, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x81, 0x04, 0x00, 0x00, + 0x26, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBF, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC2, 0x0F, 0x00, 0x00, + 0xBF, 0x0F, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC4, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC7, 0x0F, 0x00, 0x00, 0xC4, 0x0F, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC8, 0x0F, 0x00, 0x00, + 0xC2, 0x0F, 0x00, 0x00, 0xC7, 0x0F, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x08, 0x12, 0x00, 0x00, 0xC8, 0x0F, 0x00, 0x00, + 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCF, 0x0F, 0x00, 0x00, 0xBF, 0x0F, 0x00, 0x00, + 0x4A, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD4, 0x0F, 0x00, 0x00, 0xC4, 0x0F, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD5, 0x0F, 0x00, 0x00, + 0xCF, 0x0F, 0x00, 0x00, 0xD4, 0x0F, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x12, 0x00, 0x00, 0xD5, 0x0F, 0x00, 0x00, + 0x08, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xD9, 0x0F, 0x00, 0x00, 0x0E, 0x12, 0x00, 0x00, + 0x17, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDB, 0x0F, 0x00, 0x00, 0xD9, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDE, 0x0F, 0x00, 0x00, + 0xDB, 0x0F, 0x00, 0x00, 0xDB, 0x0F, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xD9, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE3, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE4, 0x0F, 0x00, 0x00, + 0xDE, 0x0F, 0x00, 0x00, 0xE3, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE7, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xE4, 0x0F, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEA, 0x0F, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xE7, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEC, 0x0F, 0x00, 0x00, 0xEA, 0x0F, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEF, 0x0F, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, 0xE7, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF1, 0x0F, 0x00, 0x00, + 0xEF, 0x0F, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF4, 0x0F, 0x00, 0x00, 0xEC, 0x0F, 0x00, 0x00, + 0xEC, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF7, 0x0F, 0x00, 0x00, 0xF1, 0x0F, 0x00, 0x00, 0xF1, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFA, 0x0F, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0xF4, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0xFA, 0x0F, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0xF7, 0x0F, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x2C, 0x07, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0xA0, 0x0F, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x10, 0x00, 0x00, 0xA3, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00, 0x00, + 0x9C, 0x04, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, 0x6F, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x16, 0x08, 0x00, 0x00, 0x74, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x08, 0x00, 0x00, + 0x79, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x19, 0x08, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, + 0x16, 0x08, 0x00, 0x00, 0x18, 0x08, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x12, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x26, 0x10, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, + 0x12, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x10, 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, + 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2C, 0x10, 0x00, 0x00, 0x26, 0x10, 0x00, 0x00, 0x2B, 0x10, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1B, 0x12, 0x00, 0x00, + 0x2C, 0x10, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x10, 0x00, 0x00, + 0x23, 0x10, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x38, 0x10, 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x39, 0x10, 0x00, 0x00, 0x33, 0x10, 0x00, 0x00, 0x38, 0x10, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x21, 0x12, 0x00, 0x00, + 0x39, 0x10, 0x00, 0x00, 0x1B, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x10, 0x00, 0x00, + 0x21, 0x12, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x00, 0x3D, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x42, 0x10, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, + 0x3D, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x47, 0x10, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, + 0x44, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x48, 0x10, 0x00, 0x00, 0x42, 0x10, 0x00, 0x00, 0x47, 0x10, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4B, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00, 0x00, + 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4E, 0x10, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x4B, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, + 0x4E, 0x10, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x53, 0x10, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, + 0x4B, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x55, 0x10, 0x00, 0x00, 0x53, 0x10, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, + 0x50, 0x10, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, 0x55, 0x10, 0x00, 0x00, + 0x55, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5E, 0x10, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, + 0x5E, 0x10, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, + 0x5B, 0x10, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x66, 0x10, 0x00, 0x00, 0x19, 0x08, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00, + 0x04, 0x10, 0x00, 0x00, 0x66, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6B, 0x10, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, + 0x63, 0x10, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x24, 0x08, 0x00, 0x00, 0xB7, 0x04, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x08, 0x00, 0x00, + 0x6F, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x28, 0x08, 0x00, 0x00, 0x74, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2A, 0x08, 0x00, 0x00, 0x79, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0x2B, 0x08, 0x00, 0x00, + 0x26, 0x08, 0x00, 0x00, 0x28, 0x08, 0x00, 0x00, 0x2A, 0x08, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, + 0x24, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8A, 0x10, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8C, 0x10, 0x00, 0x00, 0x24, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8F, 0x10, 0x00, 0x00, + 0x8C, 0x10, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x90, 0x10, 0x00, 0x00, 0x8A, 0x10, 0x00, 0x00, + 0x8F, 0x10, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2E, 0x12, 0x00, 0x00, 0x90, 0x10, 0x00, 0x00, 0x5D, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x97, 0x10, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9C, 0x10, 0x00, 0x00, + 0x8C, 0x10, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9D, 0x10, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, + 0x9C, 0x10, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x34, 0x12, 0x00, 0x00, 0x9D, 0x10, 0x00, 0x00, 0x2E, 0x12, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xA1, 0x10, 0x00, 0x00, 0x34, 0x12, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA3, 0x10, 0x00, 0x00, + 0xA1, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA6, 0x10, 0x00, 0x00, 0xA3, 0x10, 0x00, 0x00, + 0xA3, 0x10, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA8, 0x10, 0x00, 0x00, 0xA1, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, + 0xA8, 0x10, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAC, 0x10, 0x00, 0x00, 0xA6, 0x10, 0x00, 0x00, + 0xAB, 0x10, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAF, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xAC, 0x10, 0x00, 0x00, 0x14, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xAF, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB4, 0x10, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB7, 0x10, 0x00, 0x00, + 0x1C, 0x07, 0x00, 0x00, 0xAF, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB9, 0x10, 0x00, 0x00, 0xB7, 0x10, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBC, 0x10, 0x00, 0x00, 0xB4, 0x10, 0x00, 0x00, 0xB4, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBF, 0x10, 0x00, 0x00, + 0xB9, 0x10, 0x00, 0x00, 0xB9, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC2, 0x10, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0xBC, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC4, 0x10, 0x00, 0x00, 0xC2, 0x10, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC7, 0x10, 0x00, 0x00, + 0xC4, 0x10, 0x00, 0x00, 0xBF, 0x10, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xCA, 0x10, 0x00, 0x00, 0x2B, 0x08, 0x00, 0x00, + 0xC7, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xCC, 0x10, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00, 0xCA, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCF, 0x10, 0x00, 0x00, + 0x6B, 0x10, 0x00, 0x00, 0xC7, 0x10, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE4, 0x10, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0xCF, 0x10, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xED, 0x10, 0x00, 0x00, 0xE4, 0x10, 0x00, 0x00, 0xE4, 0x10, 0x00, 0x00, + 0xE4, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x3B, 0x08, 0x00, 0x00, 0xCC, 0x10, 0x00, 0x00, 0xED, 0x10, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3C, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3C, 0x07, 0x00, 0x00, + 0x3B, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x3D, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x5A, 0x07, 0x00, 0x00, 0x3C, 0x08, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x1A, 0x05, 0x00, 0x00, 0x1B, 0x05, 0x00, 0x00, 0x08, 0x05, 0x00, 0x00, + 0xD1, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1C, 0x05, 0x00, 0x00, 0x3D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x1B, 0x05, 0x00, 0x00, 0x1C, 0x05, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x1A, 0x05, 0x00, 0x00, 0x1D, 0x05, 0x00, 0x00, + 0x08, 0x05, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1E, 0x05, 0x00, 0x00, 0x3D, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x1D, 0x05, 0x00, 0x00, + 0x1E, 0x05, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1A, 0x05, 0x00, 0x00, + 0x1F, 0x05, 0x00, 0x00, 0x08, 0x05, 0x00, 0x00, 0x5D, 0x02, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x00, + 0x3D, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x1F, 0x05, 0x00, 0x00, 0x20, 0x05, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x1A, 0x05, 0x00, 0x00, 0x21, 0x05, 0x00, 0x00, 0x08, 0x05, 0x00, 0x00, + 0x61, 0x02, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x21, 0x05, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.spv new file mode 100644 index 000000000..7c391bd01 Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.txt new file mode 100644 index 000000000..58c62e211 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.txt @@ -0,0 +1,797 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 4702 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %xe_frag_color %gl_FragCoord + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %XeFsrEasuConstants "XeFsrEasuConstants" + OpMemberName %XeFsrEasuConstants 0 "xe_fsr_easu_input_output_size_ratio" + OpMemberName %XeFsrEasuConstants 1 "xe_fsr_easu_input_size_inv" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpName %gl_FragCoord "gl_FragCoord" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpMemberDecorate %XeFsrEasuConstants 0 Offset 16 + OpMemberDecorate %XeFsrEasuConstants 1 Offset 24 + OpDecorate %XeFsrEasuConstants Block + OpDecorate %xe_frag_color Location 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v2float = OpTypeVector %float 2 + %v3float = OpTypeVector %float 3 + %v4float = OpTypeVector %float 4 + %uint = OpTypeInt 32 0 + %bool = OpTypeBool + %v2uint = OpTypeVector %uint 2 + %v4uint = OpTypeVector %uint 4 + %float_1 = OpConstant %float 1 + %float_0 = OpConstant %float 0 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_1597275508 = OpConstant %uint 1597275508 + %uint_1 = OpConstant %uint 1 + %185 = OpTypeImage %float 2D 0 0 0 1 Unknown + %186 = OpTypeSampledImage %185 +%_ptr_UniformConstant_186 = OpTypePointer UniformConstant %186 + %xe_texture = OpVariable %_ptr_UniformConstant_186 UniformConstant + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 + %int_1 = OpConstant %int 1 + %int_2 = OpConstant %int 2 + %uint_0 = OpConstant %uint 0 +%float_0_400000006 = OpConstant %float 0.400000006 + %float_n1 = OpConstant %float -1 +%float_1_5625 = OpConstant %float 1.5625 +%float_n0_5625 = OpConstant %float -0.5625 + %float_0_5 = OpConstant %float 0.5 + %uint_2 = OpConstant %uint 2 + %uint_3 = OpConstant %uint 3 +%float_3_05175781en05 = OpConstant %float 3.05175781e-05 + %float_n0_5 = OpConstant %float -0.5 +%float_n0_289999992 = OpConstant %float -0.289999992 + %909 = OpConstantComposite %v2float %float_0 %float_n1 + %936 = OpConstantComposite %v2float %float_1 %float_n1 + %963 = OpConstantComposite %v2float %float_n1 %float_1 + %990 = OpConstantComposite %v2float %float_0 %float_1 + %1044 = OpConstantComposite %v2float %float_n1 %float_0 + %1071 = OpConstantComposite %v2float %float_1 %float_1 + %float_2 = OpConstant %float 2 + %1099 = OpConstantComposite %v2float %float_2 %float_1 + %1126 = OpConstantComposite %v2float %float_2 %float_0 + %1153 = OpConstantComposite %v2float %float_1 %float_0 + %1180 = OpConstantComposite %v2float %float_1 %float_2 + %1207 = OpConstantComposite %v2float %float_0 %float_2 +%XeFsrEasuConstants = OpTypeStruct %v2float %v2float +%_ptr_PushConstant_XeFsrEasuConstants = OpTypePointer PushConstant %XeFsrEasuConstants + %_ = OpVariable %_ptr_PushConstant_XeFsrEasuConstants PushConstant +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %1265 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_n1 + %1272 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_2 + %float_4 = OpConstant %float 4 +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%_ptr_Output_float = OpTypePointer Output %float + %4665 = OpConstantComposite %v2float %float_0_5 %float_0_5 + %4666 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5 + %4701 = OpUndef %v2float + %main = OpFunction %void None %3 + %5 = OpLabel + %1250 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_0 + %1251 = OpLoad %v2float %1250 + %1252 = OpBitcast %v2uint %1251 + %1255 = OpVectorTimesScalar %v2float %1251 %float_0_5 + %1257 = OpFSub %v2float %1255 %4665 + %1258 = OpBitcast %v2uint %1257 + %1266 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_1 + %1267 = OpLoad %v2float %1266 + %1268 = OpVectorShuffle %v4float %1267 %1267 0 1 0 1 + %1269 = OpFMul %v4float %1265 %1268 + %1270 = OpBitcast %v4uint %1269 + %1276 = OpFMul %v4float %1272 %1268 + %1277 = OpBitcast %v4uint %1276 + %1282 = OpAccessChain %_ptr_PushConstant_float %_ %int_1 %uint_1 + %1283 = OpLoad %float %1282 + %1284 = OpFMul %float %float_4 %1283 + %1285 = OpBitcast %uint %1284 + %1291 = OpLoad %v4float %gl_FragCoord + %1292 = OpVectorShuffle %v2float %1291 %1291 0 1 + %1293 = OpConvertFToU %v2uint %1292 + %1555 = OpConvertUToF %v2float %1293 + %1561 = OpBitcast %v2float %1252 + %1562 = OpFMul %v2float %1555 %1561 + %1568 = OpBitcast %v2float %1258 + %1569 = OpFAdd %v2float %1562 %1568 + %1571 = OpExtInst %v2float %1 Floor %1569 + %1574 = OpFSub %v2float %1569 %1571 + %1578 = OpCompositeExtract %uint %1270 0 + %1579 = OpCompositeExtract %uint %1270 1 + %1580 = OpCompositeConstruct %v2uint %1578 %1579 + %1581 = OpBitcast %v2float %1580 + %1582 = OpFMul %v2float %1571 %1581 + %1585 = OpCompositeExtract %uint %1270 2 + %1586 = OpCompositeExtract %uint %1270 3 + %1587 = OpCompositeConstruct %v2uint %1585 %1586 + %1588 = OpBitcast %v2float %1587 + %1589 = OpFAdd %v2float %1582 %1588 + %1593 = OpCompositeExtract %uint %1277 0 + %1594 = OpCompositeExtract %uint %1277 1 + %1595 = OpCompositeConstruct %v2uint %1593 %1594 + %1596 = OpBitcast %v2float %1595 + %1597 = OpFAdd %v2float %1589 %1596 + %1601 = OpCompositeExtract %uint %1277 2 + %1602 = OpCompositeExtract %uint %1277 3 + %1603 = OpCompositeConstruct %v2uint %1601 %1602 + %1604 = OpBitcast %v2float %1603 + %1605 = OpFAdd %v2float %1589 %1604 + %1611 = OpCompositeConstruct %v2uint %uint_0 %1285 + %1612 = OpBitcast %v2float %1611 + %1613 = OpFAdd %v2float %1589 %1612 + %2112 = OpLoad %186 %xe_texture + %2114 = OpImageGather %v4float %2112 %1589 %int_0 + %2119 = OpImageGather %v4float %2112 %1589 %int_1 + %2124 = OpImageGather %v4float %2112 %1589 %int_2 + %2129 = OpImageGather %v4float %2112 %1597 %int_0 + %2134 = OpImageGather %v4float %2112 %1597 %int_1 + %2139 = OpImageGather %v4float %2112 %1597 %int_2 + %2144 = OpImageGather %v4float %2112 %1605 %int_0 + %2149 = OpImageGather %v4float %2112 %1605 %int_1 + %2154 = OpImageGather %v4float %2112 %1605 %int_2 + %2159 = OpImageGather %v4float %2112 %1613 %int_0 + %2164 = OpImageGather %v4float %2112 %1613 %int_1 + %2169 = OpImageGather %v4float %2112 %1613 %int_2 + %1640 = OpFMul %v4float %2124 %4666 + %1643 = OpFMul %v4float %2114 %4666 + %1645 = OpFAdd %v4float %1643 %2119 + %1646 = OpFAdd %v4float %1640 %1645 + %1649 = OpFMul %v4float %2139 %4666 + %1652 = OpFMul %v4float %2129 %4666 + %1654 = OpFAdd %v4float %1652 %2134 + %1655 = OpFAdd %v4float %1649 %1654 + %1658 = OpFMul %v4float %2154 %4666 + %1661 = OpFMul %v4float %2144 %4666 + %1663 = OpFAdd %v4float %1661 %2149 + %1664 = OpFAdd %v4float %1658 %1663 + %1667 = OpFMul %v4float %2169 %4666 + %1670 = OpFMul %v4float %2159 %4666 + %1672 = OpFAdd %v4float %1670 %2164 + %1673 = OpFAdd %v4float %1667 %1672 + %1675 = OpCompositeExtract %float %1646 0 + %1677 = OpCompositeExtract %float %1646 1 + %1679 = OpCompositeExtract %float %1655 0 + %1681 = OpCompositeExtract %float %1655 1 + %1683 = OpCompositeExtract %float %1655 2 + %1685 = OpCompositeExtract %float %1655 3 + %1687 = OpCompositeExtract %float %1664 0 + %1689 = OpCompositeExtract %float %1664 1 + %1691 = OpCompositeExtract %float %1664 2 + %1693 = OpCompositeExtract %float %1664 3 + %1695 = OpCompositeExtract %float %1673 2 + %1697 = OpCompositeExtract %float %1673 3 + %2258 = OpCompositeExtract %float %1574 0 + %2259 = OpFSub %float %float_1 %2258 + %2262 = OpCompositeExtract %float %1574 1 + %2263 = OpFSub %float %float_1 %2262 + %2264 = OpFMul %float %2259 %2263 + %2296 = OpFSub %float %1693 %1683 + %2299 = OpFSub %float %1683 %1685 + %2301 = OpExtInst %float %1 FAbs %2296 + %2303 = OpExtInst %float %1 FAbs %2299 + %2304 = OpExtInst %float %1 FMax %2301 %2303 + %2386 = OpBitcast %uint %2304 + %2387 = OpISub %uint %uint_2129690299 %2386 + %2388 = OpBitcast %float %2387 + %2309 = OpFSub %float %1693 %1685 + %2312 = OpFMul %float %2309 %2264 + %2318 = OpExtInst %float %1 FAbs %2309 + %2320 = OpFMul %float %2318 %2388 + %2399 = OpExtInst %float %1 FClamp %2320 %float_0 %float_1 + %2324 = OpFMul %float %2399 %2399 + %2327 = OpFMul %float %2324 %2264 + %2332 = OpFSub %float %1681 %1683 + %2335 = OpFSub %float %1683 %1675 + %2337 = OpExtInst %float %1 FAbs %2332 + %2339 = OpExtInst %float %1 FAbs %2335 + %2340 = OpExtInst %float %1 FMax %2337 %2339 + %2411 = OpBitcast %uint %2340 + %2412 = OpISub %uint %uint_2129690299 %2411 + %2413 = OpBitcast %float %2412 + %2345 = OpFSub %float %1681 %1675 + %2348 = OpFMul %float %2345 %2264 + %2354 = OpExtInst %float %1 FAbs %2345 + %2356 = OpFMul %float %2354 %2413 + %2424 = OpExtInst %float %1 FClamp %2356 %float_0 %float_1 + %2360 = OpFMul %float %2424 %2424 + %2363 = OpFMul %float %2360 %2264 + %2365 = OpFAdd %float %2327 %2363 + %2471 = OpFMul %float %2258 %2263 + %2493 = OpFSub %float %1691 %1693 + %2498 = OpExtInst %float %1 FAbs %2493 + %2501 = OpExtInst %float %1 FMax %2498 %2301 + %2583 = OpBitcast %uint %2501 + %2584 = OpISub %uint %uint_2129690299 %2583 + %2585 = OpBitcast %float %2584 + %2506 = OpFSub %float %1691 %1683 + %2509 = OpFMul %float %2506 %2471 + %2512 = OpFAdd %float %2312 %2509 + %2515 = OpExtInst %float %1 FAbs %2506 + %2517 = OpFMul %float %2515 %2585 + %2596 = OpExtInst %float %1 FClamp %2517 %float_0 %float_1 + %2521 = OpFMul %float %2596 %2596 + %2524 = OpFMul %float %2521 %2471 + %2526 = OpFAdd %float %2365 %2524 + %2529 = OpFSub %float %1687 %1693 + %2532 = OpFSub %float %1693 %1677 + %2534 = OpExtInst %float %1 FAbs %2529 + %2536 = OpExtInst %float %1 FAbs %2532 + %2537 = OpExtInst %float %1 FMax %2534 %2536 + %2608 = OpBitcast %uint %2537 + %2609 = OpISub %uint %uint_2129690299 %2608 + %2610 = OpBitcast %float %2609 + %2542 = OpFSub %float %1687 %1677 + %2545 = OpFMul %float %2542 %2471 + %2548 = OpFAdd %float %2348 %2545 + %2551 = OpExtInst %float %1 FAbs %2542 + %2553 = OpFMul %float %2551 %2610 + %2621 = OpExtInst %float %1 FClamp %2553 %float_0 %float_1 + %2557 = OpFMul %float %2621 %2621 + %2560 = OpFMul %float %2557 %2471 + %2562 = OpFAdd %float %2526 %2560 + %2678 = OpFMul %float %2259 %2262 + %2690 = OpFSub %float %1687 %1681 + %2693 = OpFSub %float %1681 %1679 + %2695 = OpExtInst %float %1 FAbs %2690 + %2697 = OpExtInst %float %1 FAbs %2693 + %2698 = OpExtInst %float %1 FMax %2695 %2697 + %2780 = OpBitcast %uint %2698 + %2781 = OpISub %uint %uint_2129690299 %2780 + %2782 = OpBitcast %float %2781 + %2703 = OpFSub %float %1687 %1679 + %2706 = OpFMul %float %2703 %2678 + %2709 = OpFAdd %float %2512 %2706 + %2712 = OpExtInst %float %1 FAbs %2703 + %2714 = OpFMul %float %2712 %2782 + %2793 = OpExtInst %float %1 FClamp %2714 %float_0 %float_1 + %2718 = OpFMul %float %2793 %2793 + %2721 = OpFMul %float %2718 %2678 + %2723 = OpFAdd %float %2562 %2721 + %2726 = OpFSub %float %1697 %1681 + %2731 = OpExtInst %float %1 FAbs %2726 + %2734 = OpExtInst %float %1 FMax %2731 %2337 + %2805 = OpBitcast %uint %2734 + %2806 = OpISub %uint %uint_2129690299 %2805 + %2807 = OpBitcast %float %2806 + %2739 = OpFSub %float %1697 %1683 + %2742 = OpFMul %float %2739 %2678 + %2745 = OpFAdd %float %2548 %2742 + %2748 = OpExtInst %float %1 FAbs %2739 + %2750 = OpFMul %float %2748 %2807 + %2818 = OpExtInst %float %1 FClamp %2750 %float_0 %float_1 + %2754 = OpFMul %float %2818 %2818 + %2757 = OpFMul %float %2754 %2678 + %2759 = OpFAdd %float %2723 %2757 + %2883 = OpFMul %float %2258 %2262 + %2887 = OpFSub %float %1689 %1687 + %2892 = OpExtInst %float %1 FAbs %2887 + %2895 = OpExtInst %float %1 FMax %2892 %2695 + %2977 = OpBitcast %uint %2895 + %2978 = OpISub %uint %uint_2129690299 %2977 + %2979 = OpBitcast %float %2978 + %2900 = OpFSub %float %1689 %1681 + %2903 = OpFMul %float %2900 %2883 + %2906 = OpFAdd %float %2709 %2903 + %4398 = OpCompositeInsert %v2float %2906 %4701 0 + %2909 = OpExtInst %float %1 FAbs %2900 + %2911 = OpFMul %float %2909 %2979 + %2990 = OpExtInst %float %1 FClamp %2911 %float_0 %float_1 + %2915 = OpFMul %float %2990 %2990 + %2918 = OpFMul %float %2915 %2883 + %2920 = OpFAdd %float %2759 %2918 + %2923 = OpFSub %float %1695 %1687 + %2928 = OpExtInst %float %1 FAbs %2923 + %2931 = OpExtInst %float %1 FMax %2928 %2534 + %3002 = OpBitcast %uint %2931 + %3003 = OpISub %uint %uint_2129690299 %3002 + %3004 = OpBitcast %float %3003 + %2936 = OpFSub %float %1695 %1693 + %2939 = OpFMul %float %2936 %2883 + %2942 = OpFAdd %float %2745 %2939 + %4401 = OpCompositeInsert %v2float %2942 %4398 1 + %2945 = OpExtInst %float %1 FAbs %2936 + %2947 = OpFMul %float %2945 %3004 + %3015 = OpExtInst %float %1 FClamp %2947 %float_0 %float_1 + %2951 = OpFMul %float %3015 %3015 + %2954 = OpFMul %float %2951 %2883 + %2956 = OpFAdd %float %2920 %2954 + %1746 = OpFMul %v2float %4401 %4401 + %1748 = OpCompositeExtract %float %1746 0 + %1750 = OpCompositeExtract %float %1746 1 + %1751 = OpFAdd %float %1748 %1750 + %1754 = OpFOrdLessThan %bool %1751 %float_3_05175781en05 + %3031 = OpBitcast %uint %1751 + %3033 = OpShiftRightLogical %uint %3031 %uint_1 + %3034 = OpISub %uint %uint_1597275508 %3033 + %3035 = OpBitcast %float %3034 + OpBranch %1762 + %1762 = OpLabel + %4700 = OpSelect %float %1754 %float_1 %3035 + OpSelectionMerge %1770 None + OpBranchConditional %1754 %1765 %1767 + %1767 = OpLabel + OpBranch %1770 + %1765 = OpLabel + OpBranch %1770 + %1770 = OpLabel + %4670 = OpPhi %float %2906 %1767 %float_1 %1765 + %4406 = OpCompositeInsert %v2float %4670 %4401 0 + %3052 = OpCompositeConstruct %v2float %4700 %4700 + %1776 = OpFMul %v2float %4406 %3052 + %1779 = OpFMul %float %2956 %float_0_5 + %1782 = OpFMul %float %1779 %1779 + %1784 = OpCompositeExtract %float %1776 0 + %1787 = OpFMul %float %1784 %1784 + %1789 = OpCompositeExtract %float %1776 1 + %1792 = OpFMul %float %1789 %1789 + %1793 = OpFAdd %float %1787 %1792 + %1796 = OpExtInst %float %1 FAbs %1784 + %1799 = OpExtInst %float %1 FAbs %1789 + %1800 = OpExtInst %float %1 FMax %1796 %1799 + %3061 = OpBitcast %uint %1800 + %3062 = OpISub %uint %uint_2129690299 %3061 + %3063 = OpBitcast %float %3062 + %1802 = OpFMul %float %1793 %3063 + %1806 = OpFSub %float %1802 %float_1 + %1808 = OpFMul %float %1806 %1782 + %1809 = OpFAdd %float %float_1 %1808 + %1813 = OpFMul %float %float_n0_5 %1782 + %1814 = OpFAdd %float %float_1 %1813 + %1815 = OpCompositeConstruct %v2float %1809 %1814 + %1819 = OpFMul %float %float_n0_289999992 %1782 + %1820 = OpFAdd %float %float_0_5 %1819 + %3090 = OpBitcast %uint %1820 + %3091 = OpISub %uint %uint_2129690299 %3090 + %3092 = OpBitcast %float %3091 + %1824 = OpCompositeExtract %float %2129 2 + %1826 = OpCompositeExtract %float %2134 2 + %1828 = OpCompositeExtract %float %2139 2 + %1829 = OpCompositeConstruct %v3float %1824 %1826 %1828 + %1831 = OpCompositeExtract %float %2144 3 + %1833 = OpCompositeExtract %float %2149 3 + %1835 = OpCompositeExtract %float %2154 3 + %1836 = OpCompositeConstruct %v3float %1831 %1833 %1835 + %1838 = OpCompositeExtract %float %2129 1 + %1840 = OpCompositeExtract %float %2134 1 + %1842 = OpCompositeExtract %float %2139 1 + %1843 = OpCompositeConstruct %v3float %1838 %1840 %1842 + %3101 = OpExtInst %v3float %1 FMin %1836 %1843 + %3102 = OpExtInst %v3float %1 FMin %1829 %3101 + %1846 = OpCompositeExtract %float %2144 0 + %1848 = OpCompositeExtract %float %2149 0 + %1850 = OpCompositeExtract %float %2154 0 + %1851 = OpCompositeConstruct %v3float %1846 %1848 %1850 + %1852 = OpExtInst %v3float %1 FMin %3102 %1851 + %3108 = OpExtInst %v3float %1 FMax %1836 %1843 + %3109 = OpExtInst %v3float %1 FMax %1829 %3108 + %1882 = OpExtInst %v3float %1 FMax %3109 %1851 + %1886 = OpFSub %v2float %909 %1574 + %1888 = OpCompositeExtract %float %2114 0 + %1890 = OpCompositeExtract %float %2119 0 + %1892 = OpCompositeExtract %float %2124 0 + %1893 = OpCompositeConstruct %v3float %1888 %1890 %1892 + %3131 = OpCompositeExtract %float %1886 0 + %3134 = OpFMul %float %3131 %1784 + %3136 = OpCompositeExtract %float %1886 1 + %3139 = OpFMul %float %3136 %1789 + %3140 = OpFAdd %float %3134 %3139 + %4445 = OpCompositeInsert %v2float %3140 %4701 0 + %3146 = OpFNegate %float %1789 + %3147 = OpFMul %float %3131 %3146 + %3152 = OpFMul %float %3136 %1784 + %3153 = OpFAdd %float %3147 %3152 + %4451 = OpCompositeInsert %v2float %3153 %4445 1 + %3157 = OpFMul %v2float %4451 %1815 + %3159 = OpCompositeExtract %float %3157 0 + %3162 = OpFMul %float %3159 %3159 + %3164 = OpCompositeExtract %float %3157 1 + %3167 = OpFMul %float %3164 %3164 + %3168 = OpFAdd %float %3162 %3167 + %3171 = OpExtInst %float %1 FMin %3168 %3092 + %3174 = OpFMul %float %float_0_400000006 %3171 + %3176 = OpFAdd %float %3174 %float_n1 + %3179 = OpFMul %float %1820 %3171 + %3181 = OpFAdd %float %3179 %float_n1 + %3184 = OpFMul %float %3176 %3176 + %3187 = OpFMul %float %3181 %3181 + %3190 = OpFMul %float %float_1_5625 %3184 + %3192 = OpFAdd %float %3190 %float_n0_5625 + %3195 = OpFMul %float %3192 %3187 + %3198 = OpVectorTimesScalar %v3float %1893 %3195 + %1904 = OpFSub %v2float %936 %1574 + %1906 = OpCompositeExtract %float %2114 1 + %1908 = OpCompositeExtract %float %2119 1 + %1910 = OpCompositeExtract %float %2124 1 + %1911 = OpCompositeConstruct %v3float %1906 %1908 %1910 + %3231 = OpCompositeExtract %float %1904 0 + %3234 = OpFMul %float %3231 %1784 + %3236 = OpCompositeExtract %float %1904 1 + %3239 = OpFMul %float %3236 %1789 + %3240 = OpFAdd %float %3234 %3239 + %4464 = OpCompositeInsert %v2float %3240 %4701 0 + %3247 = OpFMul %float %3231 %3146 + %3252 = OpFMul %float %3236 %1784 + %3253 = OpFAdd %float %3247 %3252 + %4470 = OpCompositeInsert %v2float %3253 %4464 1 + %3257 = OpFMul %v2float %4470 %1815 + %3259 = OpCompositeExtract %float %3257 0 + %3262 = OpFMul %float %3259 %3259 + %3264 = OpCompositeExtract %float %3257 1 + %3267 = OpFMul %float %3264 %3264 + %3268 = OpFAdd %float %3262 %3267 + %3271 = OpExtInst %float %1 FMin %3268 %3092 + %3274 = OpFMul %float %float_0_400000006 %3271 + %3276 = OpFAdd %float %3274 %float_n1 + %3279 = OpFMul %float %1820 %3271 + %3281 = OpFAdd %float %3279 %float_n1 + %3284 = OpFMul %float %3276 %3276 + %3287 = OpFMul %float %3281 %3281 + %3290 = OpFMul %float %float_1_5625 %3284 + %3292 = OpFAdd %float %3290 %float_n0_5625 + %3295 = OpFMul %float %3292 %3287 + %3298 = OpVectorTimesScalar %v3float %1911 %3295 + %3300 = OpFAdd %v3float %3198 %3298 + %3303 = OpFAdd %float %3195 %3295 + %1922 = OpFSub %v2float %963 %1574 + %1924 = OpCompositeExtract %float %2129 0 + %1926 = OpCompositeExtract %float %2134 0 + %1928 = OpCompositeExtract %float %2139 0 + %1929 = OpCompositeConstruct %v3float %1924 %1926 %1928 + %3331 = OpCompositeExtract %float %1922 0 + %3334 = OpFMul %float %3331 %1784 + %3336 = OpCompositeExtract %float %1922 1 + %3339 = OpFMul %float %3336 %1789 + %3340 = OpFAdd %float %3334 %3339 + %4483 = OpCompositeInsert %v2float %3340 %4701 0 + %3347 = OpFMul %float %3331 %3146 + %3352 = OpFMul %float %3336 %1784 + %3353 = OpFAdd %float %3347 %3352 + %4489 = OpCompositeInsert %v2float %3353 %4483 1 + %3357 = OpFMul %v2float %4489 %1815 + %3359 = OpCompositeExtract %float %3357 0 + %3362 = OpFMul %float %3359 %3359 + %3364 = OpCompositeExtract %float %3357 1 + %3367 = OpFMul %float %3364 %3364 + %3368 = OpFAdd %float %3362 %3367 + %3371 = OpExtInst %float %1 FMin %3368 %3092 + %3374 = OpFMul %float %float_0_400000006 %3371 + %3376 = OpFAdd %float %3374 %float_n1 + %3379 = OpFMul %float %1820 %3371 + %3381 = OpFAdd %float %3379 %float_n1 + %3384 = OpFMul %float %3376 %3376 + %3387 = OpFMul %float %3381 %3381 + %3390 = OpFMul %float %float_1_5625 %3384 + %3392 = OpFAdd %float %3390 %float_n0_5625 + %3395 = OpFMul %float %3392 %3387 + %3398 = OpVectorTimesScalar %v3float %1929 %3395 + %3400 = OpFAdd %v3float %3300 %3398 + %3403 = OpFAdd %float %3303 %3395 + %1940 = OpFSub %v2float %990 %1574 + %3431 = OpCompositeExtract %float %1940 0 + %3434 = OpFMul %float %3431 %1784 + %3436 = OpCompositeExtract %float %1940 1 + %3439 = OpFMul %float %3436 %1789 + %3440 = OpFAdd %float %3434 %3439 + %4502 = OpCompositeInsert %v2float %3440 %4701 0 + %3447 = OpFMul %float %3431 %3146 + %3452 = OpFMul %float %3436 %1784 + %3453 = OpFAdd %float %3447 %3452 + %4508 = OpCompositeInsert %v2float %3453 %4502 1 + %3457 = OpFMul %v2float %4508 %1815 + %3459 = OpCompositeExtract %float %3457 0 + %3462 = OpFMul %float %3459 %3459 + %3464 = OpCompositeExtract %float %3457 1 + %3467 = OpFMul %float %3464 %3464 + %3468 = OpFAdd %float %3462 %3467 + %3471 = OpExtInst %float %1 FMin %3468 %3092 + %3474 = OpFMul %float %float_0_400000006 %3471 + %3476 = OpFAdd %float %3474 %float_n1 + %3479 = OpFMul %float %1820 %3471 + %3481 = OpFAdd %float %3479 %float_n1 + %3484 = OpFMul %float %3476 %3476 + %3487 = OpFMul %float %3481 %3481 + %3490 = OpFMul %float %float_1_5625 %3484 + %3492 = OpFAdd %float %3490 %float_n0_5625 + %3495 = OpFMul %float %3492 %3487 + %3498 = OpVectorTimesScalar %v3float %1843 %3495 + %3500 = OpFAdd %v3float %3400 %3498 + %3503 = OpFAdd %float %3403 %3495 + %1958 = OpFNegate %v2float %1574 + %3531 = OpCompositeExtract %float %1958 0 + %3534 = OpFMul %float %3531 %1784 + %3536 = OpCompositeExtract %float %1958 1 + %3539 = OpFMul %float %3536 %1789 + %3540 = OpFAdd %float %3534 %3539 + %4521 = OpCompositeInsert %v2float %3540 %4701 0 + %3547 = OpFMul %float %3531 %3146 + %3552 = OpFMul %float %3536 %1784 + %3553 = OpFAdd %float %3547 %3552 + %4527 = OpCompositeInsert %v2float %3553 %4521 1 + %3557 = OpFMul %v2float %4527 %1815 + %3559 = OpCompositeExtract %float %3557 0 + %3562 = OpFMul %float %3559 %3559 + %3564 = OpCompositeExtract %float %3557 1 + %3567 = OpFMul %float %3564 %3564 + %3568 = OpFAdd %float %3562 %3567 + %3571 = OpExtInst %float %1 FMin %3568 %3092 + %3574 = OpFMul %float %float_0_400000006 %3571 + %3576 = OpFAdd %float %3574 %float_n1 + %3579 = OpFMul %float %1820 %3571 + %3581 = OpFAdd %float %3579 %float_n1 + %3584 = OpFMul %float %3576 %3576 + %3587 = OpFMul %float %3581 %3581 + %3590 = OpFMul %float %float_1_5625 %3584 + %3592 = OpFAdd %float %3590 %float_n0_5625 + %3595 = OpFMul %float %3592 %3587 + %3598 = OpVectorTimesScalar %v3float %1829 %3595 + %3600 = OpFAdd %v3float %3500 %3598 + %3603 = OpFAdd %float %3503 %3595 + %1976 = OpFSub %v2float %1044 %1574 + %1978 = OpCompositeExtract %float %2129 3 + %1980 = OpCompositeExtract %float %2134 3 + %1982 = OpCompositeExtract %float %2139 3 + %1983 = OpCompositeConstruct %v3float %1978 %1980 %1982 + %3631 = OpCompositeExtract %float %1976 0 + %3634 = OpFMul %float %3631 %1784 + %3636 = OpCompositeExtract %float %1976 1 + %3639 = OpFMul %float %3636 %1789 + %3640 = OpFAdd %float %3634 %3639 + %4540 = OpCompositeInsert %v2float %3640 %4701 0 + %3647 = OpFMul %float %3631 %3146 + %3652 = OpFMul %float %3636 %1784 + %3653 = OpFAdd %float %3647 %3652 + %4546 = OpCompositeInsert %v2float %3653 %4540 1 + %3657 = OpFMul %v2float %4546 %1815 + %3659 = OpCompositeExtract %float %3657 0 + %3662 = OpFMul %float %3659 %3659 + %3664 = OpCompositeExtract %float %3657 1 + %3667 = OpFMul %float %3664 %3664 + %3668 = OpFAdd %float %3662 %3667 + %3671 = OpExtInst %float %1 FMin %3668 %3092 + %3674 = OpFMul %float %float_0_400000006 %3671 + %3676 = OpFAdd %float %3674 %float_n1 + %3679 = OpFMul %float %1820 %3671 + %3681 = OpFAdd %float %3679 %float_n1 + %3684 = OpFMul %float %3676 %3676 + %3687 = OpFMul %float %3681 %3681 + %3690 = OpFMul %float %float_1_5625 %3684 + %3692 = OpFAdd %float %3690 %float_n0_5625 + %3695 = OpFMul %float %3692 %3687 + %3698 = OpVectorTimesScalar %v3float %1983 %3695 + %3700 = OpFAdd %v3float %3600 %3698 + %3703 = OpFAdd %float %3603 %3695 + %1994 = OpFSub %v2float %1071 %1574 + %3731 = OpCompositeExtract %float %1994 0 + %3734 = OpFMul %float %3731 %1784 + %3736 = OpCompositeExtract %float %1994 1 + %3739 = OpFMul %float %3736 %1789 + %3740 = OpFAdd %float %3734 %3739 + %4559 = OpCompositeInsert %v2float %3740 %4701 0 + %3747 = OpFMul %float %3731 %3146 + %3752 = OpFMul %float %3736 %1784 + %3753 = OpFAdd %float %3747 %3752 + %4565 = OpCompositeInsert %v2float %3753 %4559 1 + %3757 = OpFMul %v2float %4565 %1815 + %3759 = OpCompositeExtract %float %3757 0 + %3762 = OpFMul %float %3759 %3759 + %3764 = OpCompositeExtract %float %3757 1 + %3767 = OpFMul %float %3764 %3764 + %3768 = OpFAdd %float %3762 %3767 + %3771 = OpExtInst %float %1 FMin %3768 %3092 + %3774 = OpFMul %float %float_0_400000006 %3771 + %3776 = OpFAdd %float %3774 %float_n1 + %3779 = OpFMul %float %1820 %3771 + %3781 = OpFAdd %float %3779 %float_n1 + %3784 = OpFMul %float %3776 %3776 + %3787 = OpFMul %float %3781 %3781 + %3790 = OpFMul %float %float_1_5625 %3784 + %3792 = OpFAdd %float %3790 %float_n0_5625 + %3795 = OpFMul %float %3792 %3787 + %3798 = OpVectorTimesScalar %v3float %1851 %3795 + %3800 = OpFAdd %v3float %3700 %3798 + %3803 = OpFAdd %float %3703 %3795 + %2012 = OpFSub %v2float %1099 %1574 + %2014 = OpCompositeExtract %float %2144 1 + %2016 = OpCompositeExtract %float %2149 1 + %2018 = OpCompositeExtract %float %2154 1 + %2019 = OpCompositeConstruct %v3float %2014 %2016 %2018 + %3831 = OpCompositeExtract %float %2012 0 + %3834 = OpFMul %float %3831 %1784 + %3836 = OpCompositeExtract %float %2012 1 + %3839 = OpFMul %float %3836 %1789 + %3840 = OpFAdd %float %3834 %3839 + %4578 = OpCompositeInsert %v2float %3840 %4701 0 + %3847 = OpFMul %float %3831 %3146 + %3852 = OpFMul %float %3836 %1784 + %3853 = OpFAdd %float %3847 %3852 + %4584 = OpCompositeInsert %v2float %3853 %4578 1 + %3857 = OpFMul %v2float %4584 %1815 + %3859 = OpCompositeExtract %float %3857 0 + %3862 = OpFMul %float %3859 %3859 + %3864 = OpCompositeExtract %float %3857 1 + %3867 = OpFMul %float %3864 %3864 + %3868 = OpFAdd %float %3862 %3867 + %3871 = OpExtInst %float %1 FMin %3868 %3092 + %3874 = OpFMul %float %float_0_400000006 %3871 + %3876 = OpFAdd %float %3874 %float_n1 + %3879 = OpFMul %float %1820 %3871 + %3881 = OpFAdd %float %3879 %float_n1 + %3884 = OpFMul %float %3876 %3876 + %3887 = OpFMul %float %3881 %3881 + %3890 = OpFMul %float %float_1_5625 %3884 + %3892 = OpFAdd %float %3890 %float_n0_5625 + %3895 = OpFMul %float %3892 %3887 + %3898 = OpVectorTimesScalar %v3float %2019 %3895 + %3900 = OpFAdd %v3float %3800 %3898 + %3903 = OpFAdd %float %3803 %3895 + %2030 = OpFSub %v2float %1126 %1574 + %2032 = OpCompositeExtract %float %2144 2 + %2034 = OpCompositeExtract %float %2149 2 + %2036 = OpCompositeExtract %float %2154 2 + %2037 = OpCompositeConstruct %v3float %2032 %2034 %2036 + %3931 = OpCompositeExtract %float %2030 0 + %3934 = OpFMul %float %3931 %1784 + %3936 = OpCompositeExtract %float %2030 1 + %3939 = OpFMul %float %3936 %1789 + %3940 = OpFAdd %float %3934 %3939 + %4597 = OpCompositeInsert %v2float %3940 %4701 0 + %3947 = OpFMul %float %3931 %3146 + %3952 = OpFMul %float %3936 %1784 + %3953 = OpFAdd %float %3947 %3952 + %4603 = OpCompositeInsert %v2float %3953 %4597 1 + %3957 = OpFMul %v2float %4603 %1815 + %3959 = OpCompositeExtract %float %3957 0 + %3962 = OpFMul %float %3959 %3959 + %3964 = OpCompositeExtract %float %3957 1 + %3967 = OpFMul %float %3964 %3964 + %3968 = OpFAdd %float %3962 %3967 + %3971 = OpExtInst %float %1 FMin %3968 %3092 + %3974 = OpFMul %float %float_0_400000006 %3971 + %3976 = OpFAdd %float %3974 %float_n1 + %3979 = OpFMul %float %1820 %3971 + %3981 = OpFAdd %float %3979 %float_n1 + %3984 = OpFMul %float %3976 %3976 + %3987 = OpFMul %float %3981 %3981 + %3990 = OpFMul %float %float_1_5625 %3984 + %3992 = OpFAdd %float %3990 %float_n0_5625 + %3995 = OpFMul %float %3992 %3987 + %3998 = OpVectorTimesScalar %v3float %2037 %3995 + %4000 = OpFAdd %v3float %3900 %3998 + %4003 = OpFAdd %float %3903 %3995 + %2048 = OpFSub %v2float %1153 %1574 + %4031 = OpCompositeExtract %float %2048 0 + %4034 = OpFMul %float %4031 %1784 + %4036 = OpCompositeExtract %float %2048 1 + %4039 = OpFMul %float %4036 %1789 + %4040 = OpFAdd %float %4034 %4039 + %4616 = OpCompositeInsert %v2float %4040 %4701 0 + %4047 = OpFMul %float %4031 %3146 + %4052 = OpFMul %float %4036 %1784 + %4053 = OpFAdd %float %4047 %4052 + %4622 = OpCompositeInsert %v2float %4053 %4616 1 + %4057 = OpFMul %v2float %4622 %1815 + %4059 = OpCompositeExtract %float %4057 0 + %4062 = OpFMul %float %4059 %4059 + %4064 = OpCompositeExtract %float %4057 1 + %4067 = OpFMul %float %4064 %4064 + %4068 = OpFAdd %float %4062 %4067 + %4071 = OpExtInst %float %1 FMin %4068 %3092 + %4074 = OpFMul %float %float_0_400000006 %4071 + %4076 = OpFAdd %float %4074 %float_n1 + %4079 = OpFMul %float %1820 %4071 + %4081 = OpFAdd %float %4079 %float_n1 + %4084 = OpFMul %float %4076 %4076 + %4087 = OpFMul %float %4081 %4081 + %4090 = OpFMul %float %float_1_5625 %4084 + %4092 = OpFAdd %float %4090 %float_n0_5625 + %4095 = OpFMul %float %4092 %4087 + %4098 = OpVectorTimesScalar %v3float %1836 %4095 + %4100 = OpFAdd %v3float %4000 %4098 + %4103 = OpFAdd %float %4003 %4095 + %2066 = OpFSub %v2float %1180 %1574 + %2068 = OpCompositeExtract %float %2159 2 + %2070 = OpCompositeExtract %float %2164 2 + %2072 = OpCompositeExtract %float %2169 2 + %2073 = OpCompositeConstruct %v3float %2068 %2070 %2072 + %4131 = OpCompositeExtract %float %2066 0 + %4134 = OpFMul %float %4131 %1784 + %4136 = OpCompositeExtract %float %2066 1 + %4139 = OpFMul %float %4136 %1789 + %4140 = OpFAdd %float %4134 %4139 + %4635 = OpCompositeInsert %v2float %4140 %4701 0 + %4147 = OpFMul %float %4131 %3146 + %4152 = OpFMul %float %4136 %1784 + %4153 = OpFAdd %float %4147 %4152 + %4641 = OpCompositeInsert %v2float %4153 %4635 1 + %4157 = OpFMul %v2float %4641 %1815 + %4159 = OpCompositeExtract %float %4157 0 + %4162 = OpFMul %float %4159 %4159 + %4164 = OpCompositeExtract %float %4157 1 + %4167 = OpFMul %float %4164 %4164 + %4168 = OpFAdd %float %4162 %4167 + %4171 = OpExtInst %float %1 FMin %4168 %3092 + %4174 = OpFMul %float %float_0_400000006 %4171 + %4176 = OpFAdd %float %4174 %float_n1 + %4179 = OpFMul %float %1820 %4171 + %4181 = OpFAdd %float %4179 %float_n1 + %4184 = OpFMul %float %4176 %4176 + %4187 = OpFMul %float %4181 %4181 + %4190 = OpFMul %float %float_1_5625 %4184 + %4192 = OpFAdd %float %4190 %float_n0_5625 + %4195 = OpFMul %float %4192 %4187 + %4198 = OpVectorTimesScalar %v3float %2073 %4195 + %4200 = OpFAdd %v3float %4100 %4198 + %4203 = OpFAdd %float %4103 %4195 + %2084 = OpFSub %v2float %1207 %1574 + %2086 = OpCompositeExtract %float %2159 3 + %2088 = OpCompositeExtract %float %2164 3 + %2090 = OpCompositeExtract %float %2169 3 + %2091 = OpCompositeConstruct %v3float %2086 %2088 %2090 + %4231 = OpCompositeExtract %float %2084 0 + %4234 = OpFMul %float %4231 %1784 + %4236 = OpCompositeExtract %float %2084 1 + %4239 = OpFMul %float %4236 %1789 + %4240 = OpFAdd %float %4234 %4239 + %4654 = OpCompositeInsert %v2float %4240 %4701 0 + %4247 = OpFMul %float %4231 %3146 + %4252 = OpFMul %float %4236 %1784 + %4253 = OpFAdd %float %4247 %4252 + %4660 = OpCompositeInsert %v2float %4253 %4654 1 + %4257 = OpFMul %v2float %4660 %1815 + %4259 = OpCompositeExtract %float %4257 0 + %4262 = OpFMul %float %4259 %4259 + %4264 = OpCompositeExtract %float %4257 1 + %4267 = OpFMul %float %4264 %4264 + %4268 = OpFAdd %float %4262 %4267 + %4271 = OpExtInst %float %1 FMin %4268 %3092 + %4274 = OpFMul %float %float_0_400000006 %4271 + %4276 = OpFAdd %float %4274 %float_n1 + %4279 = OpFMul %float %1820 %4271 + %4281 = OpFAdd %float %4279 %float_n1 + %4284 = OpFMul %float %4276 %4276 + %4287 = OpFMul %float %4281 %4281 + %4290 = OpFMul %float %float_1_5625 %4284 + %4292 = OpFAdd %float %4290 %float_n0_5625 + %4295 = OpFMul %float %4292 %4287 + %4298 = OpVectorTimesScalar %v3float %2091 %4295 + %4300 = OpFAdd %v3float %4200 %4298 + %4303 = OpFAdd %float %4203 %4295 + %4324 = OpFDiv %float %float_1 %4303 + %4333 = OpCompositeConstruct %v3float %4324 %4324 %4324 + %2107 = OpFMul %v3float %4300 %4333 + %2108 = OpExtInst %v3float %1 FMax %1852 %2107 + %2109 = OpExtInst %v3float %1 FMin %1882 %2108 + %1307 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + %1308 = OpCompositeExtract %float %2109 0 + OpStore %1307 %1308 + %1309 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + %1310 = OpCompositeExtract %float %2109 1 + OpStore %1309 %1310 + %1311 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + %1312 = OpCompositeExtract %float %2109 2 + OpStore %1311 %1312 + %1313 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %1313 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.h new file mode 100644 index 000000000..ab805e7bf --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.h @@ -0,0 +1,819 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_fsr_rcas_dither.frag +const uint8_t guest_output_ffx_fsr_rcas_dither_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x4E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0xA6, 0x03, 0x00, 0x00, 0xBD, 0x03, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x95, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xA6, 0x03, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, + 0xAA, 0x03, 0x00, 0x00, 0x58, 0x65, 0x46, 0x73, 0x72, 0x52, 0x63, 0x61, + 0x73, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, + 0x06, 0x00, 0x0A, 0x00, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x73, 0x72, 0x5F, 0x72, 0x63, 0x61, 0x73, 0x5F, + 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, + 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0C, 0x00, 0xAA, 0x03, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, 0x73, 0x72, 0x5F, 0x72, + 0x63, 0x61, 0x73, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, + 0x73, 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x73, 0x65, 0x74, 0x75, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xAC, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0xBD, 0x03, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x95, 0x01, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x95, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xA6, 0x03, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xAA, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xAA, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0xAA, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xBD, 0x03, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x49, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, + 0xE7, 0xE6, 0x66, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4C, 0x00, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0xA8, 0xA7, 0xA7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0x9F, 0x9E, 0x1E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, + 0xB6, 0xB5, 0xB5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x87, 0x86, 0x06, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0xA0, 0x9F, 0x9F, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0xD2, 0xD1, 0xD1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x95, 0x94, 0x94, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x92, 0x91, 0x91, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0xBE, 0xBD, 0xBD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5B, 0x00, 0x00, 0x00, 0x8F, 0x8E, 0x0E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, + 0x9E, 0x9D, 0x9D, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5E, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x8A, 0x89, 0x89, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xA3, 0xA2, 0x22, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0xFD, 0xFC, 0xFC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, + 0x90, 0x8F, 0x8F, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0xD1, 0xD0, 0xD0, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, + 0xBC, 0xBB, 0xBB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0xFE, 0xFD, 0xFD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0xA1, 0xA0, 0x20, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6A, 0x00, 0x00, 0x00, 0xBB, 0xBA, 0x3A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x90, 0x8F, 0x8F, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6D, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0xDC, 0xDB, 0xDB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0xC2, 0xC1, 0xC1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xCF, 0xCE, 0x4E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, + 0x82, 0x81, 0x81, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0xD8, 0xD7, 0xD7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x00, 0xD0, 0xCF, 0xCF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0xF4, 0xF3, 0xF3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xE7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0xEB, 0xEA, 0x6A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, + 0xC8, 0xC7, 0xC7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0xD3, 0xD2, 0x52, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0xC0, 0xBF, 0xBF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, + 0xDF, 0xDE, 0x5E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0xDF, 0xDE, 0x5E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, + 0x8C, 0x8B, 0x8B, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8B, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, + 0xBA, 0xB9, 0xB9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0xD2, 0xD1, 0xD1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x91, 0x00, 0x00, 0x00, 0x86, 0x85, 0x85, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0xD9, 0xD8, 0x58, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0xD0, 0xCF, 0xCF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x91, 0x90, 0x90, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xDD, 0xDC, 0xDC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, + 0xB4, 0xB3, 0xB3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, + 0x9C, 0x9B, 0x9B, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9D, 0x00, 0x00, 0x00, 0xBE, 0xBD, 0xBD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, + 0xF8, 0xF7, 0xF7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA0, 0x00, 0x00, 0x00, 0xC7, 0xC6, 0x46, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, + 0xFC, 0xFB, 0xFB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, + 0x83, 0x82, 0x02, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA6, 0x00, 0x00, 0x00, 0xF4, 0xF3, 0xF3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, + 0xAD, 0xAC, 0xAC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA9, 0x00, 0x00, 0x00, 0xB4, 0xB3, 0xB3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, + 0xF2, 0xF1, 0xF1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0xBF, 0xBE, 0x3E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0xEE, 0xED, 0xED, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAF, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0xD1, 0xD0, 0xD0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0xC3, 0xC2, 0x42, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, + 0x91, 0x90, 0x90, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0xC4, 0xC3, 0xC3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, + 0xFB, 0xFA, 0x7A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0xFE, 0xFD, 0xFD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, + 0xE1, 0xE0, 0x60, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, + 0xCA, 0xC9, 0xC9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0xB7, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xB0, 0xAF, 0xAF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0x9C, 0x9B, 0x9B, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC4, 0x00, 0x00, 0x00, 0xCB, 0xCA, 0x4A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x8D, 0x8C, 0x8C, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x00, 0x00, 0xC2, 0xC1, 0xC1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, + 0xCB, 0xCA, 0x4A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCA, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0xFB, 0xFA, 0x7A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCD, 0x00, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, + 0x88, 0x87, 0x87, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD0, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x32, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0x84, 0x83, 0x83, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD3, 0x00, 0x00, 0x00, 0xDD, 0xDC, 0xDC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, + 0xF9, 0xF8, 0x78, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD6, 0x00, 0x00, 0x00, 0xA3, 0xA2, 0x22, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, + 0xDB, 0xDA, 0x5A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD9, 0x00, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, + 0xE8, 0xE7, 0xE7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDC, 0x00, 0x00, 0x00, 0xCF, 0xCE, 0x4E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, + 0xB3, 0xB2, 0x32, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDF, 0x00, 0x00, 0x00, 0x82, 0x81, 0x81, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, + 0xB9, 0xB8, 0x38, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE2, 0x00, 0x00, 0x00, 0xC6, 0xC5, 0xC5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xBB, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE5, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0x98, 0x97, 0x97, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE8, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, + 0xC9, 0xC8, 0x48, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEB, 0x00, 0x00, 0x00, 0xC4, 0xC3, 0xC3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, + 0xB1, 0xB0, 0xB0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xF8, 0xF7, 0xF7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0x93, 0x92, 0x12, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF1, 0x00, 0x00, 0x00, 0xF1, 0xF0, 0xF0, 0x38, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, + 0x97, 0x96, 0x16, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF4, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, + 0xE9, 0xE8, 0x68, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF7, 0x00, 0x00, 0x00, 0xC7, 0xC6, 0x46, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, + 0xC0, 0xBF, 0xBF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0x8F, 0x8E, 0x0E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x00, 0x00, 0x94, 0x93, 0x93, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x85, 0x84, 0x84, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x93, 0x92, 0x12, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0xEE, 0xED, 0xED, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x98, 0x97, 0x97, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0xC3, 0xC2, 0x42, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, + 0xF1, 0xF0, 0xF0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x01, 0x00, 0x00, 0xA0, 0x9F, 0x9F, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0xC1, 0xC0, 0xC0, 0x37, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x01, 0x00, 0x00, 0xFC, 0xFB, 0xFB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, + 0xBB, 0xBA, 0x3A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0C, 0x01, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, + 0xA2, 0xA1, 0xA1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0xD9, 0xD8, 0x58, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x8A, 0x89, 0x89, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, + 0xBF, 0xBE, 0x3E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x12, 0x01, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0xFD, 0xFC, 0xFC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x01, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, + 0xB5, 0xB4, 0xB4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x18, 0x01, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x86, 0x85, 0x85, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, + 0xCE, 0xCD, 0xCD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1B, 0x01, 0x00, 0x00, 0xC1, 0xC0, 0xC0, 0xB7, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1D, 0x01, 0x00, 0x00, + 0xD3, 0xD2, 0x52, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1E, 0x01, 0x00, 0x00, 0xEB, 0xEA, 0x6A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0x9F, 0x9E, 0x1E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x21, 0x01, 0x00, 0x00, 0xB1, 0xB0, 0xB0, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3B, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, + 0xC6, 0xC5, 0xC5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x27, 0x01, 0x00, 0x00, 0xD7, 0xD6, 0x56, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, + 0x85, 0x84, 0x84, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0xC8, 0xC7, 0xC7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x94, 0x93, 0x93, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0xBD, 0xBC, 0xBC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2D, 0x01, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, + 0xB6, 0xB5, 0xB5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x92, 0x91, 0x91, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, + 0xE7, 0xE6, 0x66, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x33, 0x01, 0x00, 0x00, 0x99, 0x98, 0x18, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0xE1, 0xE0, 0x60, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x36, 0x01, 0x00, 0x00, 0x95, 0x94, 0x94, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, + 0xA6, 0xA5, 0xA5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x39, 0x01, 0x00, 0x00, 0x87, 0x86, 0x06, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, + 0xF6, 0xF5, 0xF5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3C, 0x01, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3D, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, + 0x81, 0x80, 0x00, 0x37, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3F, 0x01, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, + 0xC5, 0xC4, 0xC4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x42, 0x01, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, + 0xA2, 0xA1, 0xA1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x45, 0x01, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, + 0xD7, 0xD6, 0x56, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x48, 0x01, 0x00, 0x00, 0xF2, 0xF1, 0xF1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0x39, + 0x2C, 0x00, 0x03, 0x01, 0x49, 0x00, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, + 0x4A, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x4D, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x59, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, + 0x6B, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, + 0x6E, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, + 0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, + 0x7A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x7D, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, + 0x86, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, + 0x8C, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00, + 0x9E, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, + 0xA1, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xA4, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, + 0xA7, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, + 0xAA, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, + 0xAD, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, + 0xB0, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, + 0xB3, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, + 0xB6, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, + 0xB9, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, + 0xC5, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, + 0xCB, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, + 0xCE, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, + 0xD1, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, + 0xD4, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, + 0xD7, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, + 0xDA, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, + 0xDD, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, + 0xE3, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, + 0xE6, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, + 0xE9, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, + 0xEC, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, + 0xF2, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, + 0xF5, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, + 0xFB, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, + 0x07, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, + 0x0A, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, + 0x0D, 0x01, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, + 0x13, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, + 0x16, 0x01, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, + 0x1C, 0x01, 0x00, 0x00, 0x1D, 0x01, 0x00, 0x00, 0x1E, 0x01, 0x00, 0x00, + 0x1F, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, + 0x22, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, + 0x25, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, + 0x28, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x2B, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x2D, 0x01, 0x00, 0x00, + 0x2E, 0x01, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, + 0x31, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, + 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, + 0x37, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, + 0x3A, 0x01, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, + 0x3D, 0x01, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, 0x3F, 0x01, 0x00, 0x00, + 0x40, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, + 0x43, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, + 0x46, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, + 0x49, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x54, 0x01, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7F, 0x01, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x19, 0x00, 0x09, 0x00, 0x92, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x03, 0x00, 0x93, 0x01, 0x00, 0x00, 0x92, 0x01, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x93, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x94, 0x01, 0x00, 0x00, + 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x9B, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xA9, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x05, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0xAA, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, + 0xA9, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0xB1, 0x01, 0x00, 0x00, 0xA9, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, 0xBD, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0xBE, 0x01, 0x00, 0x00, 0xBD, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, 0xC5, 0x01, 0x00, 0x00, + 0x98, 0x01, 0x00, 0x00, 0xBD, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3E, 0x17, 0x00, 0x04, 0x00, 0xE4, 0x02, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xED, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x40, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0xBE, 0x20, 0x00, 0x04, 0x00, + 0xA5, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xA5, 0x03, 0x00, 0x00, 0xA6, 0x03, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0xAA, 0x03, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xAB, 0x03, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAA, 0x03, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xAB, 0x03, 0x00, 0x00, 0xAC, 0x03, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xAD, 0x03, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xB3, 0x03, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xBC, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xBC, 0x03, 0x00, 0x00, + 0xBD, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xC7, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x06, 0x00, 0x9B, 0x01, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x06, 0x00, 0x9B, 0x01, 0x00, 0x00, 0xD5, 0x03, 0x00, 0x00, + 0x6E, 0x01, 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDD, 0x03, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x4D, 0x07, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x54, 0x01, 0x00, 0x00, + 0x1B, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xA7, 0x03, 0x00, 0x00, 0xA6, 0x03, 0x00, 0x00, + 0x4F, 0x00, 0x07, 0x00, 0xE4, 0x02, 0x00, 0x00, 0xA8, 0x03, 0x00, 0x00, + 0xA7, 0x03, 0x00, 0x00, 0xA7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0xA9, 0x03, 0x00, 0x00, 0xA8, 0x03, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xAD, 0x03, 0x00, 0x00, 0xAE, 0x03, 0x00, 0x00, 0xAC, 0x03, 0x00, 0x00, + 0x98, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0xAF, 0x03, 0x00, 0x00, 0xAE, 0x03, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0xB0, 0x03, 0x00, 0x00, 0xA9, 0x03, 0x00, 0x00, + 0xAF, 0x03, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xB1, 0x03, 0x00, 0x00, 0xB0, 0x03, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xB3, 0x03, 0x00, 0x00, 0xB4, 0x03, 0x00, 0x00, 0xAC, 0x03, 0x00, 0x00, + 0xBD, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB5, 0x03, 0x00, 0x00, 0xB4, 0x03, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB6, 0x03, 0x00, 0x00, 0xB5, 0x03, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x66, 0x04, 0x00, 0x00, + 0xB1, 0x03, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x68, 0x04, 0x00, 0x00, 0x66, 0x04, 0x00, 0x00, 0xAA, 0x01, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x93, 0x01, 0x00, 0x00, 0xD2, 0x05, 0x00, 0x00, + 0x95, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x92, 0x01, 0x00, 0x00, + 0xD4, 0x05, 0x00, 0x00, 0xD2, 0x05, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xD5, 0x05, 0x00, 0x00, 0xD4, 0x05, 0x00, 0x00, + 0x68, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD7, 0x05, 0x00, 0x00, + 0xD5, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD8, 0x05, 0x00, 0x00, 0xD5, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD9, 0x05, 0x00, 0x00, 0xD5, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x6C, 0x04, 0x00, 0x00, + 0x66, 0x04, 0x00, 0x00, 0xB1, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x92, 0x01, 0x00, 0x00, 0xDF, 0x05, 0x00, 0x00, 0xD2, 0x05, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xE0, 0x05, 0x00, 0x00, + 0xDF, 0x05, 0x00, 0x00, 0x6C, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x98, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE2, 0x05, 0x00, 0x00, 0xE0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE3, 0x05, 0x00, 0x00, + 0xE0, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE4, 0x05, 0x00, 0x00, 0xE0, 0x05, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x92, 0x01, 0x00, 0x00, + 0xEA, 0x05, 0x00, 0x00, 0xD2, 0x05, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xEB, 0x05, 0x00, 0x00, 0xEA, 0x05, 0x00, 0x00, + 0x66, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xED, 0x05, 0x00, 0x00, + 0xEB, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEE, 0x05, 0x00, 0x00, 0xEB, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEF, 0x05, 0x00, 0x00, 0xEB, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x73, 0x04, 0x00, 0x00, + 0x66, 0x04, 0x00, 0x00, 0xBE, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x92, 0x01, 0x00, 0x00, 0xF5, 0x05, 0x00, 0x00, 0xD2, 0x05, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xF6, 0x05, 0x00, 0x00, + 0xF5, 0x05, 0x00, 0x00, 0x73, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x98, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF8, 0x05, 0x00, 0x00, 0xF6, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF9, 0x05, 0x00, 0x00, + 0xF6, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFA, 0x05, 0x00, 0x00, 0xF6, 0x05, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x77, 0x04, 0x00, 0x00, 0x66, 0x04, 0x00, 0x00, 0xC5, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x92, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0xD2, 0x05, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x01, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x77, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x04, 0x06, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, + 0x01, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xE2, 0x05, 0x00, 0x00, 0xF8, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xD7, 0x05, 0x00, 0x00, + 0x83, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x17, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x84, 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8A, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xE3, 0x05, 0x00, 0x00, 0xF9, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8B, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xD8, 0x05, 0x00, 0x00, + 0x8A, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1D, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x8B, 0x06, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x91, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xE4, 0x05, 0x00, 0x00, 0xFA, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x92, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xD9, 0x05, 0x00, 0x00, + 0x91, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x23, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x92, 0x06, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x98, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE2, 0x05, 0x00, 0x00, 0xF8, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x99, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xD7, 0x05, 0x00, 0x00, + 0x98, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x29, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x99, 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9F, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE3, 0x05, 0x00, 0x00, 0xF9, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA0, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xD8, 0x05, 0x00, 0x00, + 0x9F, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2F, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xA0, 0x06, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA6, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE4, 0x05, 0x00, 0x00, 0xFA, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA7, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xD9, 0x05, 0x00, 0x00, + 0xA6, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x35, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xA7, 0x06, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x38, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x17, 0x05, 0x00, 0x00, 0xED, 0x05, 0x00, 0x00, + 0x88, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x06, 0x00, 0x00, + 0x68, 0x02, 0x00, 0x00, 0x29, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3D, 0x05, 0x00, 0x00, 0x38, 0x05, 0x00, 0x00, + 0xB0, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x40, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x1D, 0x05, 0x00, 0x00, 0xEE, 0x05, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBC, 0x06, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, + 0x2F, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x45, 0x05, 0x00, 0x00, 0x40, 0x05, 0x00, 0x00, 0xBC, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x48, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x23, 0x05, 0x00, 0x00, + 0xEF, 0x05, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC8, 0x06, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x35, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4D, 0x05, 0x00, 0x00, + 0x48, 0x05, 0x00, 0x00, 0xC8, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x52, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x29, 0x05, 0x00, 0x00, 0xED, 0x05, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x53, 0x05, 0x00, 0x00, + 0x6E, 0x01, 0x00, 0x00, 0x52, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x56, 0x05, 0x00, 0x00, 0xED, 0x02, 0x00, 0x00, + 0x17, 0x05, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x59, 0x05, 0x00, 0x00, 0x56, 0x05, 0x00, 0x00, 0xE7, 0x02, 0x00, 0x00, + 0x88, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD4, 0x06, 0x00, 0x00, + 0x6E, 0x01, 0x00, 0x00, 0x59, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x05, 0x00, 0x00, 0x53, 0x05, 0x00, 0x00, + 0xD4, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x60, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x2F, 0x05, 0x00, 0x00, 0xEE, 0x05, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x61, 0x05, 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, + 0x60, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x64, 0x05, 0x00, 0x00, 0xED, 0x02, 0x00, 0x00, 0x1D, 0x05, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x67, 0x05, 0x00, 0x00, + 0x64, 0x05, 0x00, 0x00, 0xE7, 0x02, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE0, 0x06, 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, + 0x67, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x69, 0x05, 0x00, 0x00, 0x61, 0x05, 0x00, 0x00, 0xE0, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6E, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x35, 0x05, 0x00, 0x00, + 0xEF, 0x05, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6F, 0x05, 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, 0x6E, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x05, 0x00, 0x00, + 0xED, 0x02, 0x00, 0x00, 0x23, 0x05, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x75, 0x05, 0x00, 0x00, 0x72, 0x05, 0x00, 0x00, + 0xE7, 0x02, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEC, 0x06, 0x00, 0x00, 0x6E, 0x01, 0x00, 0x00, 0x75, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x77, 0x05, 0x00, 0x00, + 0x6F, 0x05, 0x00, 0x00, 0xEC, 0x06, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x79, 0x05, 0x00, 0x00, 0x3D, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x79, 0x05, 0x00, 0x00, + 0x5B, 0x05, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7D, 0x05, 0x00, 0x00, 0x45, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x7D, 0x05, 0x00, 0x00, 0x69, 0x05, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x81, 0x05, 0x00, 0x00, + 0x4D, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x83, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x81, 0x05, 0x00, 0x00, 0x77, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x7F, 0x05, 0x00, 0x00, 0x83, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x7B, 0x05, 0x00, 0x00, + 0xF8, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8A, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xF9, 0x06, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8B, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x4E, 0x03, 0x00, 0x00, 0x8A, 0x05, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8E, 0x05, 0x00, 0x00, + 0xB6, 0x03, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8F, 0x05, 0x00, 0x00, 0x8B, 0x05, 0x00, 0x00, 0x8E, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x92, 0x05, 0x00, 0x00, + 0xED, 0x02, 0x00, 0x00, 0x8F, 0x05, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x94, 0x05, 0x00, 0x00, 0x92, 0x05, 0x00, 0x00, + 0x6E, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x07, 0x00, 0x00, 0x94, 0x05, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0B, 0x07, 0x00, 0x00, 0x7F, 0x01, 0x00, 0x00, + 0x0A, 0x07, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0C, 0x07, 0x00, 0x00, 0x0B, 0x07, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0F, 0x07, 0x00, 0x00, 0x0C, 0x07, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x07, 0x00, 0x00, + 0x0F, 0x07, 0x00, 0x00, 0x94, 0x05, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, 0x11, 0x07, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x14, 0x07, 0x00, 0x00, 0x0C, 0x07, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x44, 0x07, 0x00, 0x00, + 0xD7, 0x05, 0x00, 0x00, 0xE2, 0x05, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x45, 0x07, 0x00, 0x00, 0x44, 0x07, 0x00, 0x00, + 0x03, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x46, 0x07, 0x00, 0x00, 0x45, 0x07, 0x00, 0x00, 0xF8, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA4, 0x05, 0x00, 0x00, + 0x8F, 0x05, 0x00, 0x00, 0x46, 0x07, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA6, 0x05, 0x00, 0x00, 0xA4, 0x05, 0x00, 0x00, + 0xED, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA8, 0x05, 0x00, 0x00, 0xA6, 0x05, 0x00, 0x00, 0x14, 0x07, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x47, 0x07, 0x00, 0x00, + 0xD8, 0x05, 0x00, 0x00, 0xE3, 0x05, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x48, 0x07, 0x00, 0x00, 0x47, 0x07, 0x00, 0x00, + 0x04, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x49, 0x07, 0x00, 0x00, 0x48, 0x07, 0x00, 0x00, 0xF9, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB7, 0x05, 0x00, 0x00, + 0x8F, 0x05, 0x00, 0x00, 0x49, 0x07, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB9, 0x05, 0x00, 0x00, 0xB7, 0x05, 0x00, 0x00, + 0xEE, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBB, 0x05, 0x00, 0x00, 0xB9, 0x05, 0x00, 0x00, 0x14, 0x07, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4A, 0x07, 0x00, 0x00, + 0xD9, 0x05, 0x00, 0x00, 0xE4, 0x05, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4B, 0x07, 0x00, 0x00, 0x4A, 0x07, 0x00, 0x00, + 0x05, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4C, 0x07, 0x00, 0x00, 0x4B, 0x07, 0x00, 0x00, 0xFA, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCA, 0x05, 0x00, 0x00, + 0x8F, 0x05, 0x00, 0x00, 0x4C, 0x07, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCC, 0x05, 0x00, 0x00, 0xCA, 0x05, 0x00, 0x00, + 0xEF, 0x05, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCE, 0x05, 0x00, 0x00, 0xCC, 0x05, 0x00, 0x00, 0x14, 0x07, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xC7, 0x03, 0x00, 0x00, 0xC8, 0x03, 0x00, 0x00, + 0xBD, 0x03, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xC8, 0x03, 0x00, 0x00, 0xA8, 0x05, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC7, 0x03, 0x00, 0x00, 0xCA, 0x03, 0x00, 0x00, 0xBD, 0x03, 0x00, 0x00, + 0x4B, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xCA, 0x03, 0x00, 0x00, + 0xBB, 0x05, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xC7, 0x03, 0x00, 0x00, + 0xCC, 0x03, 0x00, 0x00, 0xBD, 0x03, 0x00, 0x00, 0xD1, 0x01, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xCC, 0x03, 0x00, 0x00, 0xCE, 0x05, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xCD, 0x03, 0x00, 0x00, + 0xBD, 0x03, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, 0x9B, 0x01, 0x00, 0x00, + 0xCE, 0x03, 0x00, 0x00, 0xCD, 0x03, 0x00, 0x00, 0xCD, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, + 0xB1, 0x03, 0x00, 0x00, 0x4D, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x22, 0x07, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x23, 0x07, 0x00, 0x00, 0x22, 0x07, 0x00, 0x00, 0x4E, 0x01, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x07, 0x00, 0x00, + 0x20, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x26, 0x07, 0x00, 0x00, 0x23, 0x07, 0x00, 0x00, + 0x25, 0x07, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x1B, 0x07, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x27, 0x07, 0x00, 0x00, 0x1B, 0x07, 0x00, 0x00, 0x26, 0x07, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x28, 0x07, 0x00, 0x00, + 0x27, 0x07, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x9B, 0x01, 0x00, 0x00, + 0xD2, 0x03, 0x00, 0x00, 0x28, 0x07, 0x00, 0x00, 0x28, 0x07, 0x00, 0x00, + 0x28, 0x07, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x9B, 0x01, 0x00, 0x00, + 0xD3, 0x03, 0x00, 0x00, 0xCE, 0x03, 0x00, 0x00, 0xD2, 0x03, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x9B, 0x01, 0x00, 0x00, 0xD6, 0x03, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xD3, 0x03, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0xD5, 0x03, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD8, 0x03, 0x00, 0x00, 0xD6, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xC8, 0x03, 0x00, 0x00, + 0xD8, 0x03, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDA, 0x03, 0x00, 0x00, 0xD6, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xCA, 0x03, 0x00, 0x00, 0xDA, 0x03, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDC, 0x03, 0x00, 0x00, + 0xD6, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xCC, 0x03, 0x00, 0x00, 0xDC, 0x03, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC7, 0x03, 0x00, 0x00, 0xDE, 0x03, 0x00, 0x00, 0xBD, 0x03, 0x00, 0x00, + 0xDD, 0x03, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xDE, 0x03, 0x00, 0x00, + 0x6E, 0x01, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.spv new file mode 100644 index 000000000..5490f7982 Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.txt new file mode 100644 index 000000000..60ea16b8a --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.txt @@ -0,0 +1,494 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 1870 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeFsrRcasConstants "XeFsrRcasConstants" + OpMemberName %XeFsrRcasConstants 0 "xe_fsr_rcas_output_offset" + OpMemberName %XeFsrRcasConstants 1 "xe_fsr_rcas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeFsrRcasConstants 0 Offset 16 + OpMemberDecorate %XeFsrRcasConstants 1 Offset 24 + OpDecorate %XeFsrRcasConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %float = OpTypeFloat 32 +%_ptr_Function_float = OpTypePointer Function %float + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v4float = OpTypeVector %float 4 + %uint_15 = OpConstant %uint 15 + %uint_256 = OpConstant %uint 256 +%_arr_float_uint_256 = OpTypeArray %float %uint_256 +%float_n0_00100337015 = OpConstant %float -0.00100337015 +%float_0_000880821084 = OpConstant %float 0.000880821084 +%float_0_00169270835 = OpConstant %float 0.00169270835 +%float_n0_00155484071 = OpConstant %float -0.00155484071 +%float_0_00127910543 = OpConstant %float 0.00127910543 +%float_n0_000605085806 = OpConstant %float -0.000605085806 +%float_0_00106464466 = OpConstant %float 0.00106464466 +%float_n0_00138633582 = OpConstant %float -0.00138633582 +%float_0_00135569857 = OpConstant %float 0.00135569857 +%float_0_000513174047 = OpConstant %float 0.000513174047 +%float_0_00121783093 = OpConstant %float 0.00121783093 +%float_n0_00160079659 = OpConstant %float -0.00160079659 +%float_0_00058976718 = OpConstant %float 0.00058976718 +%float_n0_00028339462 = OpConstant %float -0.00028339462 +%float_0_00111060054 = OpConstant %float 0.00111060054 +%float_n0_00141697307 = OpConstant %float -0.00141697307 +%float_0_00144761032 = OpConstant %float 0.00144761032 +%float_n0_0005438113 = OpConstant %float -0.0005438113 +%float_0_00013020834 = OpConstant %float 0.00013020834 +%float_n0_0012025123 = OpConstant %float -0.0012025123 +%float_0_000436580885 = OpConstant %float 0.000436580885 +%float_n0_00104932603 = OpConstant %float -0.00104932603 +%float_0_000620404433 = OpConstant %float 0.000620404433 +%float_n0_000482536765 = OpConstant %float -0.000482536765 +%float_0_00187653187 = OpConstant %float 0.00187653187 +%float_n0_00109528191 = OpConstant %float -0.00109528191 +%float_n9_95710798en05 = OpConstant %float -9.95710798e-05 +%float_n0_000528492674 = OpConstant %float -0.000528492674 +%float_0_0014322917 = OpConstant %float 0.0014322917 +%float_n0_00193780637 = OpConstant %float -0.00193780637 +%float_n0_000696997566 = OpConstant %float -0.000696997566 +%float_3_829657en05 = OpConstant %float 3.829657e-05 +%float_0_000712316192 = OpConstant %float 0.000712316192 +%float_n0_00130974269 = OpConstant %float -0.00130974269 +%float_0_00109528191 = OpConstant %float 0.00109528191 +%float_n0_000298713247 = OpConstant %float -0.000298713247 +%float_0_00175398286 = OpConstant %float 0.00175398286 +%float_n0_00167738972 = OpConstant %float -0.00167738972 +%float_0_00147824758 = OpConstant %float 0.00147824758 +%float_n3_829657en05 = OpConstant %float -3.829657e-05 +%float_0_000788909325 = OpConstant %float 0.000788909325 +%float_n0_00183057599 = OpConstant %float -0.00183057599 +%float_0_000298713247 = OpConstant %float 0.000298713247 +%float_0_000988051528 = OpConstant %float 0.000988051528 +%float_n0_00117187505 = OpConstant %float -0.00117187505 +%float_0_00017616422 = OpConstant %float 0.00017616422 +%float_0_00164675247 = OpConstant %float 0.00164675247 +%float_n0_00158547796 = OpConstant %float -0.00158547796 +%float_0_000344669126 = OpConstant %float 0.000344669126 +%float_0_00186121324 = OpConstant %float 0.00186121324 +%float_n0_00176930148 = OpConstant %float -0.00176930148 +%float_n0_000865502458 = OpConstant %float -0.000865502458 +%float_0_000896139711 = OpConstant %float 0.000896139711 +%float_0_000160845593 = OpConstant %float 0.000160845593 +%float_n0_000926776964 = OpConstant %float -0.000926776964 +%float_n0_00152420346 = OpConstant %float -0.00152420346 +%float_n0_000651041686 = OpConstant %float -0.000651041686 +%float_0_00129442406 = OpConstant %float 0.00129442406 +%float_n0_000804227951 = OpConstant %float -0.000804227951 +%float_n0_00146292895 = OpConstant %float -0.00146292895 +%float_0_00179993873 = OpConstant %float 0.00179993873 +%float_n0_000850183831 = OpConstant %float -0.000850183831 +%float_0_000850183831 = OpConstant %float 0.000850183831 +%float_n0_000451899512 = OpConstant %float -0.000451899512 +%float_n0_00106464466 = OpConstant %float -0.00106464466 +%float_n0_000145526967 = OpConstant %float -0.000145526967 +%float_0_000237438726 = OpConstant %float 0.000237438726 +%float_0_00141697307 = OpConstant %float 0.00141697307 +%float_n0_00058976718 = OpConstant %float -0.00058976718 +%float_n0_000191482846 = OpConstant %float -0.000191482846 +%float_0_00160079659 = OpConstant %float 0.00160079659 +%float_0_00101868878 = OpConstant %float 0.00101868878 +%float_0_000405943632 = OpConstant %float 0.000405943632 +%float_n0_000206801473 = OpConstant %float -0.000206801473 +%float_0_00158547796 = OpConstant %float 0.00158547796 +%float_0_000651041686 = OpConstant %float 0.000651041686 +%float_n6_89338267en05 = OpConstant %float -6.89338267e-05 +%float_0_000421262259 = OpConstant %float 0.000421262259 +%float_n0_00164675247 = OpConstant %float -0.00164675247 +%float_0_00137101719 = OpConstant %float 0.00137101719 +%float_0_000926776964 = OpConstant %float 0.000926776964 +%float_n0_000666360313 = OpConstant %float -0.000666360313 +%float_0_00118719367 = OpConstant %float 0.00118719367 +%float_n0_00144761032 = OpConstant %float -0.00144761032 +%float_0_000574448553 = OpConstant %float 0.000574448553 +%float_n0_00189185049 = OpConstant %float -0.00189185049 +%float_0_000758272072 = OpConstant %float 0.000758272072 +%float_n0_00129442406 = OpConstant %float -0.00129442406 +%float_0_00192248775 = OpConstant %float 0.00192248775 +%float_n0_0016620711 = OpConstant %float -0.0016620711 +%float_n0_00103400741 = OpConstant %float -0.00103400741 +%float_n0_000497855421 = OpConstant %float -0.000497855421 +%float_n0_00186121324 = OpConstant %float -0.00186121324 +%float_0_0012025123 = OpConstant %float 0.0012025123 +%float_n0_0003293505 = OpConstant %float -0.0003293505 +%float_n0_00137101719 = OpConstant %float -0.00137101719 +%float_0_00163143384 = OpConstant %float 0.00163143384 +%float_n0_00184589461 = OpConstant %float -0.00184589461 +%float_0_000727634819 = OpConstant %float 0.000727634819 +%float_n0_000911458337 = OpConstant %float -0.000911458337 +%float_0_00181525736 = OpConstant %float 0.00181525736 +%float_n0_00114123779 = OpConstant %float -0.00114123779 +%float_n0_000375306379 = OpConstant %float -0.000375306379 +%float_9_95710798en05 = OpConstant %float 9.95710798e-05 +%float_n0_000742953445 = OpConstant %float -0.000742953445 +%float_0_00117187505 = OpConstant %float 0.00117187505 +%float_6_89338267en05 = OpConstant %float 6.89338267e-05 +%float_0_0014935662 = OpConstant %float 0.0014935662 +%float_0_000972732843 = OpConstant %float 0.000972732843 +%float_n0_000957414217 = OpConstant %float -0.000957414217 +%float_0_00193780637 = OpConstant %float 0.00193780637 +%float_0_000528492674 = OpConstant %float 0.000528492674 +%float_5_36151965en05 = OpConstant %float 5.36151965e-05 +%float_n0_00124846818 = OpConstant %float -0.00124846818 +%float_n0_000268075994 = OpConstant %float -0.000268075994 +%float_0_00153952208 = OpConstant %float 0.00153952208 +%float_n7_65931418en06 = OpConstant %float -7.65931418e-06 +%float_0_000314031873 = OpConstant %float 0.000314031873 +%float_0_00134037994 = OpConstant %float 0.00134037994 +%float_n0_00175398286 = OpConstant %float -0.00175398286 +%float_0_000497855421 = OpConstant %float 0.000497855421 +%float_n0_00118719367 = OpConstant %float -0.00118719367 +%float_0_000773590698 = OpConstant %float 0.000773590698 +%float_n0_00134037994 = OpConstant %float -0.00134037994 +%float_0_000268075994 = OpConstant %float 0.000268075994 +%float_n0_00147824758 = OpConstant %float -0.00147824758 +%float_n0_00013020834 = OpConstant %float -0.00013020834 +%float_n0_000773590698 = OpConstant %float -0.000773590698 +%float_0_00130974269 = OpConstant %float 0.00130974269 +%float_0_000390625006 = OpConstant %float 0.000390625006 +%float_0_000957414217 = OpConstant %float 0.000957414217 +%float_n0_000467218139 = OpConstant %float -0.000467218139 +%float_n0_00153952208 = OpConstant %float -0.00153952208 +%float_0_00103400741 = OpConstant %float 0.00103400741 +%float_n0_000681678939 = OpConstant %float -0.000681678939 +%float_0_00167738972 = OpConstant %float 0.00167738972 +%float_0_00100337015 = OpConstant %float 0.00100337015 +%float_n0_000421262259 = OpConstant %float -0.000421262259 +%float_0_00178462011 = OpConstant %float 0.00178462011 +%float_n0_000237438726 = OpConstant %float -0.000237438726 +%float_n0_000620404433 = OpConstant %float -0.000620404433 +%float_0_0016620711 = OpConstant %float 0.0016620711 +%float_0_000834865205 = OpConstant %float 0.000834865205 +%float_n0_0017233456 = OpConstant %float -0.0017233456 +%float_n0_00107996329 = OpConstant %float -0.00107996329 +%float_0_00176930148 = OpConstant %float 0.00176930148 +%float_n0_000788909325 = OpConstant %float -0.000788909325 +%float_n0_00178462011 = OpConstant %float -0.00178462011 +%float_0_000681678939 = OpConstant %float 0.000681678939 +%float_n0_000988051528 = OpConstant %float -0.000988051528 +%float_n0_00132506131 = OpConstant %float -0.00132506131 +%float_n0_00017616422 = OpConstant %float -0.00017616422 +%float_n0_00150888483 = OpConstant %float -0.00150888483 +%float_0_0003293505 = OpConstant %float 0.0003293505 +%float_n0_001953125 = OpConstant %float -0.001953125 +%float_0_000666360313 = OpConstant %float 0.000666360313 +%float_n0_00161611522 = OpConstant %float -0.00161611522 +%float_0_00115655642 = OpConstant %float 0.00115655642 +%float_0_000451899512 = OpConstant %float 0.000451899512 +%float_n0_000436580885 = OpConstant %float -0.000436580885 +%float_0_000191482846 = OpConstant %float 0.000191482846 +%float_n0_0014935662 = OpConstant %float -0.0014935662 +%float_0_00114123779 = OpConstant %float 0.00114123779 +%float_8_42524532en05 = OpConstant %float 8.42524532e-05 +%float_0_00189185049 = OpConstant %float 0.00189185049 +%float_0_00140165444 = OpConstant %float 0.00140165444 +%float_0_000559129927 = OpConstant %float 0.000559129927 +%float_0_000114889706 = OpConstant %float 0.000114889706 +%float_0_00126378681 = OpConstant %float 0.00126378681 +%float_n0_000574448553 = OpConstant %float -0.000574448553 +%float_n0_000972732843 = OpConstant %float -0.000972732843 +%float_0_00132506131 = OpConstant %float 0.00132506131 +%float_0_000222120099 = OpConstant %float 0.000222120099 +%float_n0_000758272072 = OpConstant %float -0.000758272072 +%float_n0_00135569857 = OpConstant %float -0.00135569857 +%float_0_00146292895 = OpConstant %float 0.00146292895 +%float_0_000865502458 = OpConstant %float 0.000865502458 +%float_n0_000359987753 = OpConstant %float -0.000359987753 +%float_0_0005438113 = OpConstant %float 0.0005438113 +%float_n0_00112591917 = OpConstant %float -0.00112591917 +%float_n0_000252757367 = OpConstant %float -0.000252757367 +%float_n0_000559129927 = OpConstant %float -0.000559129927 +%float_n0_00181525736 = OpConstant %float -0.00181525736 +%float_0_0017233456 = OpConstant %float 0.0017233456 +%float_n0_00115655642 = OpConstant %float -0.00115655642 +%float_0_000742953445 = OpConstant %float 0.000742953445 +%float_0_00157015934 = OpConstant %float 0.00157015934 +%float_n0_000114889706 = OpConstant %float -0.000114889706 +%float_n0_00121783093 = OpConstant %float -0.00121783093 +%float_0_00183057599 = OpConstant %float 0.00183057599 +%float_2_29779416en05 = OpConstant %float 2.29779416e-05 +%float_n0_00192248775 = OpConstant %float -0.00192248775 +%float_0_00173866423 = OpConstant %float 0.00173866423 +%float_n0_000712316192 = OpConstant %float -0.000712316192 +%float_0_00155484071 = OpConstant %float 0.00155484071 +%float_n0_00170802698 = OpConstant %float -0.00170802698 +%float_0_00123314955 = OpConstant %float 0.00123314955 +%float_0_000206801473 = OpConstant %float 0.000206801473 +%float_0_00104932603 = OpConstant %float 0.00104932603 +%float_n0_000727634819 = OpConstant %float -0.000727634819 +%float_n0_00163143384 = OpConstant %float -0.00163143384 +%float_n0_000314031873 = OpConstant %float -0.000314031873 +%float_0_000482536765 = OpConstant %float 0.000482536765 +%float_n0_00179993873 = OpConstant %float -0.00179993873 +%float_0_00094209559 = OpConstant %float 0.00094209559 +%float_n0_000344669126 = OpConstant %float -0.000344669126 +%float_0_000696997566 = OpConstant %float 0.000696997566 +%float_n0_00101868878 = OpConstant %float -0.00101868878 +%float_n0_00157015934 = OpConstant %float -0.00157015934 +%float_n2_29779416en05 = OpConstant %float -2.29779416e-05 +%float_n0_00127910543 = OpConstant %float -0.00127910543 +%float_0_000804227951 = OpConstant %float 0.000804227951 +%float_n0_000896139711 = OpConstant %float -0.000896139711 +%float_n0_0014322917 = OpConstant %float -0.0014322917 +%float_0_000605085806 = OpConstant %float 0.000605085806 +%float_n8_42524532en05 = OpConstant %float -8.42524532e-05 +%float_0_000911458337 = OpConstant %float 0.000911458337 +%float_0_001953125 = OpConstant %float 0.001953125 +%float_n0_00140165444 = OpConstant %float -0.00140165444 +%float_n0_00063572306 = OpConstant %float -0.00063572306 +%float_0_00150888483 = OpConstant %float 0.00150888483 +%float_n0_000819546578 = OpConstant %float -0.000819546578 +%float_0_00124846818 = OpConstant %float 0.00124846818 +%float_0_000252757367 = OpConstant %float 0.000252757367 +%float_0_00152420346 = OpConstant %float 0.00152420346 +%float_0_00112591917 = OpConstant %float 0.00112591917 +%float_0_000359987753 = OpConstant %float 0.000359987753 +%float_n0_000390625006 = OpConstant %float -0.000390625006 +%float_0_00190716912 = OpConstant %float 0.00190716912 +%float_0_00138633582 = OpConstant %float 0.00138633582 +%float_n0_00111060054 = OpConstant %float -0.00111060054 +%float_0_00161611522 = OpConstant %float 0.00161611522 +%float_n0_000880821084 = OpConstant %float -0.000880821084 +%float_0_000145526967 = OpConstant %float 0.000145526967 +%float_0_00107996329 = OpConstant %float 0.00107996329 +%float_n5_36151965en05 = OpConstant %float -5.36151965e-05 +%float_0_00028339462 = OpConstant %float 0.00028339462 +%float_n0_00169270835 = OpConstant %float -0.00169270835 +%float_n0_00126378681 = OpConstant %float -0.00126378681 +%float_n0_000513174047 = OpConstant %float -0.000513174047 +%float_n0_000160845593 = OpConstant %float -0.000160845593 +%float_n0_00187653187 = OpConstant %float -0.00187653187 +%float_n0_000834865205 = OpConstant %float -0.000834865205 +%float_0_00063572306 = OpConstant %float 0.00063572306 +%float_7_65931418en06 = OpConstant %float 7.65931418e-06 +%float_n0_00190716912 = OpConstant %float -0.00190716912 +%float_n0_000222120099 = OpConstant %float -0.000222120099 +%float_0_000375306379 = OpConstant %float 0.000375306379 +%float_n0_00173866423 = OpConstant %float -0.00173866423 +%float_n0_000405943632 = OpConstant %float -0.000405943632 +%float_n0_00123314955 = OpConstant %float -0.00123314955 +%float_0_00170802698 = OpConstant %float 0.00170802698 +%float_n0_00094209559 = OpConstant %float -0.00094209559 +%float_0_000819546578 = OpConstant %float 0.000819546578 +%float_0_00184589461 = OpConstant %float 0.00184589461 +%float_0_000467218139 = OpConstant %float 0.000467218139 + %330 = OpConstantComposite %_arr_float_uint_256 %float_n0_00100337015 %float_0_000880821084 %float_0_00169270835 %float_n0_00155484071 %float_0_00127910543 %float_n0_000605085806 %float_0_00106464466 %float_n0_00138633582 %float_0_00135569857 %float_0_000513174047 %float_0_00121783093 %float_n0_00160079659 %float_0_00058976718 %float_n0_00028339462 %float_0_00111060054 %float_n0_00141697307 %float_0_00144761032 %float_n0_0005438113 %float_0_00013020834 %float_n0_0012025123 %float_0_000436580885 %float_n0_00104932603 %float_0_000620404433 %float_n0_000482536765 %float_0_00187653187 %float_n0_00109528191 %float_n9_95710798en05 %float_n0_000528492674 %float_0_0014322917 %float_n0_00193780637 %float_n0_000696997566 %float_3_829657en05 %float_0_000712316192 %float_n0_00130974269 %float_0_00109528191 %float_n0_000298713247 %float_0_00175398286 %float_n0_00167738972 %float_0_00147824758 %float_n3_829657en05 %float_0_000788909325 %float_n0_00183057599 %float_0_000298713247 %float_0_000988051528 %float_n0_00117187505 %float_0_00017616422 %float_0_00164675247 %float_n0_00158547796 %float_0_000344669126 %float_0_00186121324 %float_n0_00176930148 %float_n0_000865502458 %float_0_000896139711 %float_0_000160845593 %float_n0_000926776964 %float_n0_00152420346 %float_n0_000651041686 %float_0_00129442406 %float_n0_000804227951 %float_n0_00146292895 %float_0_00179993873 %float_n0_000850183831 %float_0_000850183831 %float_n0_000451899512 %float_n0_00106464466 %float_n0_000145526967 %float_0_000237438726 %float_0_00141697307 %float_n0_00058976718 %float_n0_000191482846 %float_0_00160079659 %float_0_00101868878 %float_0_000405943632 %float_n0_000206801473 %float_0_00158547796 %float_0_000651041686 %float_n6_89338267en05 %float_0_000421262259 %float_n0_00164675247 %float_0_00137101719 %float_0_000926776964 %float_n0_000666360313 %float_0_00118719367 %float_n0_00144761032 %float_0_000574448553 %float_n0_00189185049 %float_0_000758272072 %float_n0_00129442406 %float_0_00192248775 %float_n0_0016620711 %float_n0_00103400741 %float_n0_000497855421 %float_n0_00186121324 %float_0_0012025123 %float_n0_0003293505 %float_n0_00137101719 %float_0_00163143384 %float_n0_00184589461 %float_0_000727634819 %float_n0_000911458337 %float_0_00181525736 %float_n0_00114123779 %float_n0_000375306379 %float_9_95710798en05 %float_n0_000742953445 %float_0_00117187505 %float_6_89338267en05 %float_0_0014935662 %float_0_000972732843 %float_n0_000957414217 %float_0_00193780637 %float_0_000528492674 %float_5_36151965en05 %float_n0_00124846818 %float_n0_000268075994 %float_0_00153952208 %float_n7_65931418en06 %float_0_000314031873 %float_0_00134037994 %float_n0_00175398286 %float_0_000497855421 %float_n0_00118719367 %float_0_000773590698 %float_n0_00134037994 %float_0_000268075994 %float_n0_00147824758 %float_n0_00013020834 %float_n0_000773590698 %float_0_00130974269 %float_0_000390625006 %float_0_000957414217 %float_n0_000467218139 %float_n0_00153952208 %float_0_00103400741 %float_n0_000681678939 %float_0_00167738972 %float_0_00100337015 %float_n0_000421262259 %float_0_00178462011 %float_n0_000237438726 %float_n0_000620404433 %float_0_0016620711 %float_0_000834865205 %float_n0_0017233456 %float_n0_00107996329 %float_0_00176930148 %float_n0_000788909325 %float_n0_00178462011 %float_0_000681678939 %float_n0_000988051528 %float_n0_00132506131 %float_n0_00017616422 %float_n0_00150888483 %float_0_0003293505 %float_n0_001953125 %float_0_000666360313 %float_n0_00161611522 %float_0_00115655642 %float_0_000451899512 %float_n0_000436580885 %float_0_000191482846 %float_n0_0014935662 %float_0_00114123779 %float_8_42524532en05 %float_0_00189185049 %float_0_00140165444 %float_0_000559129927 %float_0_000114889706 %float_0_00126378681 %float_n0_000574448553 %float_n0_000972732843 %float_0_00132506131 %float_0_000222120099 %float_n0_000758272072 %float_n0_00135569857 %float_0_00146292895 %float_0_000865502458 %float_n0_000359987753 %float_0_0005438113 %float_n0_00112591917 %float_n0_000252757367 %float_n0_000559129927 %float_n0_00181525736 %float_0_0017233456 %float_n0_00115655642 %float_0_000742953445 %float_0_00157015934 %float_n0_000114889706 %float_n0_00121783093 %float_0_00183057599 %float_2_29779416en05 %float_n0_00192248775 %float_0_00173866423 %float_n0_000712316192 %float_0_00155484071 %float_n0_00170802698 %float_0_00123314955 %float_0_000206801473 %float_0_00104932603 %float_n0_000727634819 %float_n0_00163143384 %float_n0_000314031873 %float_0_000482536765 %float_n0_00179993873 %float_0_00094209559 %float_n0_000344669126 %float_0_000696997566 %float_n0_00101868878 %float_n0_00157015934 %float_n2_29779416en05 %float_n0_00127910543 %float_0_000804227951 %float_n0_000896139711 %float_n0_0014322917 %float_0_000605085806 %float_n8_42524532en05 %float_0_000911458337 %float_0_001953125 %float_n0_00140165444 %float_n0_00063572306 %float_0_00150888483 %float_n0_000819546578 %float_0_00124846818 %float_0_000252757367 %float_0_00152420346 %float_0_00112591917 %float_0_000359987753 %float_n0_000390625006 %float_0_00190716912 %float_0_00138633582 %float_n0_00111060054 %float_0_00161611522 %float_n0_000880821084 %float_0_000145526967 %float_0_00107996329 %float_n5_36151965en05 %float_0_00028339462 %float_n0_00169270835 %float_n0_00126378681 %float_n0_000513174047 %float_n0_000160845593 %float_n0_00187653187 %float_n0_000834865205 %float_0_00063572306 %float_7_65931418en06 %float_n0_00190716912 %float_n0_000222120099 %float_0_000375306379 %float_n0_00173866423 %float_n0_000405943632 %float_n0_00123314955 %float_0_00170802698 %float_n0_00094209559 %float_0_000819546578 %float_0_00184589461 %float_0_000467218139 + %uint_1 = OpConstant %uint 1 + %uint_16 = OpConstant %uint 16 + %uint_0 = OpConstant %uint 0 +%_ptr_Function__arr_float_uint_256 = OpTypePointer Function %_arr_float_uint_256 + %float_1 = OpConstant %float 1 + %float_0 = OpConstant %float 0 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %402 = OpTypeImage %float 2D 0 0 0 1 Unknown + %403 = OpTypeSampledImage %402 +%_ptr_UniformConstant_403 = OpTypePointer UniformConstant %403 + %xe_texture = OpVariable %_ptr_UniformConstant_403 UniformConstant + %int_0 = OpConstant %int 0 + %v3float = OpTypeVector %float 3 + %int_n1 = OpConstant %int -1 + %426 = OpConstantComposite %v2int %int_0 %int_n1 + %433 = OpConstantComposite %v2int %int_n1 %int_0 + %int_1 = OpConstant %int 1 + %446 = OpConstantComposite %v2int %int_1 %int_0 + %453 = OpConstantComposite %v2int %int_0 %int_1 + %uint_2 = OpConstant %uint 2 + %float_0_25 = OpConstant %float 0.25 + %v2float = OpTypeVector %float 2 + %float_n4 = OpConstant %float -4 + %float_4 = OpConstant %float 4 +%float_n0_1875 = OpConstant %float -0.1875 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeFsrRcasConstants = OpTypeStruct %v2int %float +%_ptr_PushConstant_XeFsrRcasConstants = OpTypePointer PushConstant %XeFsrRcasConstants + %_ = OpVariable %_ptr_PushConstant_XeFsrRcasConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %980 = OpConstantComposite %v3float %float_0 %float_0 %float_0 + %981 = OpConstantComposite %v3float %float_1 %float_1 %float_1 + %uint_3 = OpConstant %uint 3 + %1869 = OpConstantComposite %v2uint %uint_15 %uint_15 + %main = OpFunction %void None %3 + %5 = OpLabel + %1819 = OpVariable %_ptr_Function__arr_float_uint_256 Function + %935 = OpLoad %v4float %gl_FragCoord + %936 = OpVectorShuffle %v2float %935 %935 0 1 + %937 = OpConvertFToS %v2int %936 + %942 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %943 = OpLoad %v2int %942 + %944 = OpISub %v2int %937 %943 + %945 = OpBitcast %v2uint %944 + %948 = OpAccessChain %_ptr_PushConstant_float %_ %int_1 + %949 = OpLoad %float %948 + %950 = OpBitcast %uint %949 + %1126 = OpBitcast %v2int %945 + %1128 = OpIAdd %v2int %1126 %426 + %1490 = OpLoad %403 %xe_texture + %1492 = OpImage %402 %1490 + %1493 = OpImageFetch %v4float %1492 %1128 Lod %int_0 + %1495 = OpCompositeExtract %float %1493 0 + %1496 = OpCompositeExtract %float %1493 1 + %1497 = OpCompositeExtract %float %1493 2 + %1132 = OpIAdd %v2int %1126 %433 + %1503 = OpImage %402 %1490 + %1504 = OpImageFetch %v4float %1503 %1132 Lod %int_0 + %1506 = OpCompositeExtract %float %1504 0 + %1507 = OpCompositeExtract %float %1504 1 + %1508 = OpCompositeExtract %float %1504 2 + %1514 = OpImage %402 %1490 + %1515 = OpImageFetch %v4float %1514 %1126 Lod %int_0 + %1517 = OpCompositeExtract %float %1515 0 + %1518 = OpCompositeExtract %float %1515 1 + %1519 = OpCompositeExtract %float %1515 2 + %1139 = OpIAdd %v2int %1126 %446 + %1525 = OpImage %402 %1490 + %1526 = OpImageFetch %v4float %1525 %1139 Lod %int_0 + %1528 = OpCompositeExtract %float %1526 0 + %1529 = OpCompositeExtract %float %1526 1 + %1530 = OpCompositeExtract %float %1526 2 + %1143 = OpIAdd %v2int %1126 %453 + %1536 = OpImage %402 %1490 + %1537 = OpImageFetch %v4float %1536 %1143 Lod %int_0 + %1539 = OpCompositeExtract %float %1537 0 + %1540 = OpCompositeExtract %float %1537 1 + %1541 = OpCompositeExtract %float %1537 2 + %1667 = OpExtInst %float %1 FMin %1506 %1528 + %1668 = OpExtInst %float %1 FMin %1495 %1667 + %1303 = OpExtInst %float %1 FMin %1668 %1539 + %1674 = OpExtInst %float %1 FMin %1507 %1529 + %1675 = OpExtInst %float %1 FMin %1496 %1674 + %1309 = OpExtInst %float %1 FMin %1675 %1540 + %1681 = OpExtInst %float %1 FMin %1508 %1530 + %1682 = OpExtInst %float %1 FMin %1497 %1681 + %1315 = OpExtInst %float %1 FMin %1682 %1541 + %1688 = OpExtInst %float %1 FMax %1506 %1528 + %1689 = OpExtInst %float %1 FMax %1495 %1688 + %1321 = OpExtInst %float %1 FMax %1689 %1539 + %1695 = OpExtInst %float %1 FMax %1507 %1529 + %1696 = OpExtInst %float %1 FMax %1496 %1695 + %1327 = OpExtInst %float %1 FMax %1696 %1540 + %1702 = OpExtInst %float %1 FMax %1508 %1530 + %1703 = OpExtInst %float %1 FMax %1497 %1702 + %1333 = OpExtInst %float %1 FMax %1703 %1541 + %1336 = OpExtInst %float %1 FMin %1303 %1517 + %1712 = OpFDiv %float %float_0_25 %1321 + %1341 = OpFMul %float %1336 %1712 + %1344 = OpExtInst %float %1 FMin %1309 %1518 + %1724 = OpFDiv %float %float_0_25 %1327 + %1349 = OpFMul %float %1344 %1724 + %1352 = OpExtInst %float %1 FMin %1315 %1519 + %1736 = OpFDiv %float %float_0_25 %1333 + %1357 = OpFMul %float %1352 %1736 + %1362 = OpExtInst %float %1 FMax %1321 %1517 + %1363 = OpFSub %float %float_1 %1362 + %1366 = OpFMul %float %float_4 %1303 + %1369 = OpFAdd %float %1366 %float_n4 + %1748 = OpFDiv %float %float_1 %1369 + %1371 = OpFMul %float %1363 %1748 + %1376 = OpExtInst %float %1 FMax %1327 %1518 + %1377 = OpFSub %float %float_1 %1376 + %1380 = OpFMul %float %float_4 %1309 + %1383 = OpFAdd %float %1380 %float_n4 + %1760 = OpFDiv %float %float_1 %1383 + %1385 = OpFMul %float %1377 %1760 + %1390 = OpExtInst %float %1 FMax %1333 %1519 + %1391 = OpFSub %float %float_1 %1390 + %1394 = OpFMul %float %float_4 %1315 + %1397 = OpFAdd %float %1394 %float_n4 + %1772 = OpFDiv %float %float_1 %1397 + %1399 = OpFMul %float %1391 %1772 + %1401 = OpFNegate %float %1341 + %1403 = OpExtInst %float %1 FMax %1401 %1371 + %1405 = OpFNegate %float %1349 + %1407 = OpExtInst %float %1 FMax %1405 %1385 + %1409 = OpFNegate %float %1357 + %1411 = OpExtInst %float %1 FMax %1409 %1399 + %1784 = OpExtInst %float %1 FMax %1407 %1411 + %1785 = OpExtInst %float %1 FMax %1403 %1784 + %1418 = OpExtInst %float %1 FMin %1785 %float_0 + %1419 = OpExtInst %float %1 FMax %float_n0_1875 %1418 + %1422 = OpBitcast %float %950 + %1423 = OpFMul %float %1419 %1422 + %1426 = OpFMul %float %float_4 %1423 + %1428 = OpFAdd %float %1426 %float_1 + %1802 = OpBitcast %uint %1428 + %1803 = OpISub %uint %uint_2129764351 %1802 + %1804 = OpBitcast %float %1803 + %1807 = OpFNegate %float %1804 + %1809 = OpFMul %float %1807 %1428 + %1811 = OpFAdd %float %1809 %float_2 + %1812 = OpFMul %float %1804 %1811 + %1860 = OpFAdd %float %1495 %1506 + %1861 = OpFAdd %float %1860 %1539 + %1862 = OpFAdd %float %1861 %1528 + %1444 = OpFMul %float %1423 %1862 + %1446 = OpFAdd %float %1444 %1517 + %1448 = OpFMul %float %1446 %1812 + %1863 = OpFAdd %float %1496 %1507 + %1864 = OpFAdd %float %1863 %1540 + %1865 = OpFAdd %float %1864 %1529 + %1463 = OpFMul %float %1423 %1865 + %1465 = OpFAdd %float %1463 %1518 + %1467 = OpFMul %float %1465 %1812 + %1866 = OpFAdd %float %1497 %1508 + %1867 = OpFAdd %float %1866 %1541 + %1868 = OpFAdd %float %1867 %1530 + %1482 = OpFMul %float %1423 %1868 + %1484 = OpFAdd %float %1482 %1519 + %1486 = OpFMul %float %1484 %1812 + %968 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %968 %1448 + %970 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %970 %1467 + %972 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %972 %1486 + %973 = OpLoad %v4float %xe_frag_color + %974 = OpVectorShuffle %v3float %973 %973 0 1 2 + %1824 = OpBitwiseAnd %v2uint %945 %1869 + %1826 = OpCompositeExtract %uint %1824 1 + %1827 = OpIMul %uint %1826 %uint_16 + %1829 = OpCompositeExtract %uint %1824 0 + %1830 = OpIAdd %uint %1827 %1829 + OpStore %1819 %330 + %1831 = OpAccessChain %_ptr_Function_float %1819 %1830 + %1832 = OpLoad %float %1831 + %978 = OpCompositeConstruct %v3float %1832 %1832 %1832 + %979 = OpFAdd %v3float %974 %978 + %982 = OpExtInst %v3float %1 FClamp %979 %980 %981 + %984 = OpCompositeExtract %float %982 0 + OpStore %968 %984 + %986 = OpCompositeExtract %float %982 1 + OpStore %970 %986 + %988 = OpCompositeExtract %float %982 2 + OpStore %972 %988 + %990 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %990 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.h new file mode 100644 index 000000000..f5eb24f7e --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.h @@ -0,0 +1,345 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_fsr_rcas.frag +const uint8_t guest_output_ffx_fsr_rcas_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x15, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x8E, 0x02, 0x00, 0x00, 0xA5, 0x02, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x8E, 0x02, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x58, 0x65, 0x46, 0x73, 0x72, 0x52, 0x63, 0x61, + 0x73, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, + 0x06, 0x00, 0x0A, 0x00, 0x92, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x73, 0x72, 0x5F, 0x72, 0x63, 0x61, 0x73, 0x5F, + 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, + 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x92, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, 0x73, 0x72, 0x5F, 0x72, + 0x63, 0x61, 0x73, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, + 0x73, 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x73, 0x65, 0x74, 0x75, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x94, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0xA5, 0x02, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7B, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x8E, 0x02, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xA5, 0x02, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, + 0xFF, 0x9F, 0xF1, 0x7E, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x09, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, + 0x79, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x27, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, + 0xAB, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3E, 0x17, 0x00, 0x04, 0x00, 0xCC, 0x01, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x40, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x36, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0xBE, 0x20, 0x00, 0x04, 0x00, + 0x8D, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x8D, 0x02, 0x00, 0x00, 0x8E, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0x92, 0x02, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x93, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x92, 0x02, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x93, 0x02, 0x00, 0x00, 0x94, 0x02, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x95, 0x02, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9B, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xA4, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xA4, 0x02, 0x00, 0x00, + 0xA5, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xAF, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB5, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x8F, 0x02, 0x00, 0x00, 0x8E, 0x02, 0x00, 0x00, + 0x4F, 0x00, 0x07, 0x00, 0xCC, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x8F, 0x02, 0x00, 0x00, 0x8F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x91, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x95, 0x02, 0x00, 0x00, 0x96, 0x02, 0x00, 0x00, 0x94, 0x02, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x97, 0x02, 0x00, 0x00, 0x96, 0x02, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x98, 0x02, 0x00, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x97, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x99, 0x02, 0x00, 0x00, 0x98, 0x02, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9B, 0x02, 0x00, 0x00, 0x9C, 0x02, 0x00, 0x00, 0x94, 0x02, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9D, 0x02, 0x00, 0x00, 0x9C, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x9E, 0x02, 0x00, 0x00, 0x9D, 0x02, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x3E, 0x03, 0x00, 0x00, + 0x99, 0x02, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x40, 0x03, 0x00, 0x00, 0x3E, 0x03, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x79, 0x00, 0x00, 0x00, 0xAA, 0x04, 0x00, 0x00, + 0x7B, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x78, 0x00, 0x00, 0x00, + 0xAC, 0x04, 0x00, 0x00, 0xAA, 0x04, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xAD, 0x04, 0x00, 0x00, 0xAC, 0x04, 0x00, 0x00, + 0x40, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAF, 0x04, 0x00, 0x00, + 0xAD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, 0xAD, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB1, 0x04, 0x00, 0x00, 0xAD, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00, + 0x3E, 0x03, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x78, 0x00, 0x00, 0x00, 0xB7, 0x04, 0x00, 0x00, 0xAA, 0x04, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x29, 0x00, 0x00, 0x00, 0xB8, 0x04, 0x00, 0x00, + 0xB7, 0x04, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBA, 0x04, 0x00, 0x00, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBB, 0x04, 0x00, 0x00, + 0xB8, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBC, 0x04, 0x00, 0x00, 0xB8, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x78, 0x00, 0x00, 0x00, + 0xC2, 0x04, 0x00, 0x00, 0xAA, 0x04, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xC3, 0x04, 0x00, 0x00, 0xC2, 0x04, 0x00, 0x00, + 0x3E, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC5, 0x04, 0x00, 0x00, + 0xC3, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC6, 0x04, 0x00, 0x00, 0xC3, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC7, 0x04, 0x00, 0x00, 0xC3, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x4B, 0x03, 0x00, 0x00, + 0x3E, 0x03, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x78, 0x00, 0x00, 0x00, 0xCD, 0x04, 0x00, 0x00, 0xAA, 0x04, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x29, 0x00, 0x00, 0x00, 0xCE, 0x04, 0x00, 0x00, + 0xCD, 0x04, 0x00, 0x00, 0x4B, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD0, 0x04, 0x00, 0x00, 0xCE, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD1, 0x04, 0x00, 0x00, + 0xCE, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD2, 0x04, 0x00, 0x00, 0xCE, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x4F, 0x03, 0x00, 0x00, 0x3E, 0x03, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x78, 0x00, 0x00, 0x00, 0xD8, 0x04, 0x00, 0x00, + 0xAA, 0x04, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x29, 0x00, 0x00, 0x00, + 0xD9, 0x04, 0x00, 0x00, 0xD8, 0x04, 0x00, 0x00, 0x4F, 0x03, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDB, 0x04, 0x00, 0x00, 0xD9, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDC, 0x04, 0x00, 0x00, 0xD9, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDD, 0x04, 0x00, 0x00, + 0xD9, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5B, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xBA, 0x04, 0x00, 0x00, 0xD0, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5C, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xAF, 0x04, 0x00, 0x00, + 0x5B, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEF, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x5C, 0x05, 0x00, 0x00, 0xDB, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x62, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xBB, 0x04, 0x00, 0x00, 0xD1, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x63, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, + 0x62, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF5, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x63, 0x05, 0x00, 0x00, 0xDC, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xBC, 0x04, 0x00, 0x00, 0xD2, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6A, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xB1, 0x04, 0x00, 0x00, + 0x69, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFB, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x6A, 0x05, 0x00, 0x00, 0xDD, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x70, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xBA, 0x04, 0x00, 0x00, 0xD0, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xAF, 0x04, 0x00, 0x00, + 0x70, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x71, 0x05, 0x00, 0x00, 0xDB, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x77, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xBB, 0x04, 0x00, 0x00, 0xD1, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, + 0x77, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x78, 0x05, 0x00, 0x00, 0xDC, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7E, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xBC, 0x04, 0x00, 0x00, 0xD2, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7F, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xB1, 0x04, 0x00, 0x00, + 0x7E, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0D, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x7F, 0x05, 0x00, 0x00, 0xDD, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xEF, 0x03, 0x00, 0x00, 0xC5, 0x04, 0x00, 0x00, + 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x05, 0x00, 0x00, + 0x50, 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x15, 0x04, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, + 0x88, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x18, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xF5, 0x03, 0x00, 0x00, 0xC6, 0x04, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x94, 0x05, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0x07, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1D, 0x04, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x94, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xFB, 0x03, 0x00, 0x00, + 0xC7, 0x04, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA0, 0x05, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x0D, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x04, 0x00, 0x00, + 0x20, 0x04, 0x00, 0x00, 0xA0, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2A, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0xC5, 0x04, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x04, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x2A, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2E, 0x04, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0xEF, 0x03, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x31, 0x04, 0x00, 0x00, 0x2E, 0x04, 0x00, 0x00, 0xCF, 0x01, 0x00, 0x00, + 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAC, 0x05, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x31, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x2B, 0x04, 0x00, 0x00, + 0xAC, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x38, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x07, 0x04, 0x00, 0x00, 0xC6, 0x04, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x38, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3C, 0x04, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, 0xF5, 0x03, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3F, 0x04, 0x00, 0x00, + 0x3C, 0x04, 0x00, 0x00, 0xCF, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB8, 0x05, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x3F, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x41, 0x04, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0xB8, 0x05, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0D, 0x04, 0x00, 0x00, + 0xC7, 0x04, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x47, 0x04, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x46, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, + 0xD5, 0x01, 0x00, 0x00, 0xFB, 0x03, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4D, 0x04, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, + 0xCF, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC4, 0x05, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4D, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4F, 0x04, 0x00, 0x00, + 0x47, 0x04, 0x00, 0x00, 0xC4, 0x05, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x15, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, + 0x33, 0x04, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x55, 0x04, 0x00, 0x00, 0x1D, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x57, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x55, 0x04, 0x00, 0x00, 0x41, 0x04, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x59, 0x04, 0x00, 0x00, + 0x25, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5B, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x59, 0x04, 0x00, 0x00, 0x4F, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD0, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x57, 0x04, 0x00, 0x00, 0x5B, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD1, 0x05, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x53, 0x04, 0x00, 0x00, + 0xD0, 0x05, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x62, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xD1, 0x05, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x63, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x62, 0x04, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x66, 0x04, 0x00, 0x00, + 0x9E, 0x02, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x67, 0x04, 0x00, 0x00, 0x63, 0x04, 0x00, 0x00, 0x66, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6A, 0x04, 0x00, 0x00, + 0xD5, 0x01, 0x00, 0x00, 0x67, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6C, 0x04, 0x00, 0x00, 0x6A, 0x04, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xE2, 0x05, 0x00, 0x00, 0x6C, 0x04, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE3, 0x05, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, + 0xE2, 0x05, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE4, 0x05, 0x00, 0x00, 0xE3, 0x05, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE7, 0x05, 0x00, 0x00, 0xE4, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE9, 0x05, 0x00, 0x00, + 0xE7, 0x05, 0x00, 0x00, 0x6C, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEB, 0x05, 0x00, 0x00, 0xE9, 0x05, 0x00, 0x00, + 0x71, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEC, 0x05, 0x00, 0x00, 0xE4, 0x05, 0x00, 0x00, 0xEB, 0x05, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x06, 0x00, 0x00, + 0xAF, 0x04, 0x00, 0x00, 0xBA, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0D, 0x06, 0x00, 0x00, 0x0C, 0x06, 0x00, 0x00, + 0xDB, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0E, 0x06, 0x00, 0x00, 0x0D, 0x06, 0x00, 0x00, 0xD0, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7C, 0x04, 0x00, 0x00, + 0x67, 0x04, 0x00, 0x00, 0x0E, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7E, 0x04, 0x00, 0x00, 0x7C, 0x04, 0x00, 0x00, + 0xC5, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x80, 0x04, 0x00, 0x00, 0x7E, 0x04, 0x00, 0x00, 0xEC, 0x05, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0F, 0x06, 0x00, 0x00, + 0xB0, 0x04, 0x00, 0x00, 0xBB, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0x0F, 0x06, 0x00, 0x00, + 0xDC, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x11, 0x06, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0xD1, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8F, 0x04, 0x00, 0x00, + 0x67, 0x04, 0x00, 0x00, 0x11, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x91, 0x04, 0x00, 0x00, 0x8F, 0x04, 0x00, 0x00, + 0xC6, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x93, 0x04, 0x00, 0x00, 0x91, 0x04, 0x00, 0x00, 0xEC, 0x05, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x06, 0x00, 0x00, + 0xB1, 0x04, 0x00, 0x00, 0xBC, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x13, 0x06, 0x00, 0x00, 0x12, 0x06, 0x00, 0x00, + 0xDD, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x14, 0x06, 0x00, 0x00, 0x13, 0x06, 0x00, 0x00, 0xD2, 0x04, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA2, 0x04, 0x00, 0x00, + 0x67, 0x04, 0x00, 0x00, 0x14, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA4, 0x04, 0x00, 0x00, 0xA2, 0x04, 0x00, 0x00, + 0xC7, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA6, 0x04, 0x00, 0x00, 0xA4, 0x04, 0x00, 0x00, 0xEC, 0x05, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xAF, 0x02, 0x00, 0x00, 0xB0, 0x02, 0x00, 0x00, + 0xA5, 0x02, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xB0, 0x02, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xAF, 0x02, 0x00, 0x00, 0xB2, 0x02, 0x00, 0x00, 0xA5, 0x02, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xB2, 0x02, 0x00, 0x00, + 0x93, 0x04, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xAF, 0x02, 0x00, 0x00, + 0xB4, 0x02, 0x00, 0x00, 0xA5, 0x02, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xB4, 0x02, 0x00, 0x00, 0xA6, 0x04, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xAF, 0x02, 0x00, 0x00, 0xB6, 0x02, 0x00, 0x00, + 0xA5, 0x02, 0x00, 0x00, 0xB5, 0x02, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xB6, 0x02, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.spv new file mode 100644 index 000000000..410ccc33a Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.txt new file mode 100644 index 000000000..ca7e98acf --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.txt @@ -0,0 +1,207 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 1557 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeFsrRcasConstants "XeFsrRcasConstants" + OpMemberName %XeFsrRcasConstants 0 "xe_fsr_rcas_output_offset" + OpMemberName %XeFsrRcasConstants 1 "xe_fsr_rcas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeFsrRcasConstants 0 Offset 16 + OpMemberDecorate %XeFsrRcasConstants 1 Offset 24 + OpDecorate %XeFsrRcasConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %uint = OpTypeInt 32 0 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v4float = OpTypeVector %float 4 + %v2uint = OpTypeVector %uint 2 + %float_1 = OpConstant %float 1 + %float_0 = OpConstant %float 0 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %120 = OpTypeImage %float 2D 0 0 0 1 Unknown + %121 = OpTypeSampledImage %120 +%_ptr_UniformConstant_121 = OpTypePointer UniformConstant %121 + %xe_texture = OpVariable %_ptr_UniformConstant_121 UniformConstant + %int_0 = OpConstant %int 0 + %int_n1 = OpConstant %int -1 + %144 = OpConstantComposite %v2int %int_0 %int_n1 + %151 = OpConstantComposite %v2int %int_n1 %int_0 + %int_1 = OpConstant %int 1 + %164 = OpConstantComposite %v2int %int_1 %int_0 + %171 = OpConstantComposite %v2int %int_0 %int_1 + %uint_0 = OpConstant %uint 0 + %uint_1 = OpConstant %uint 1 + %uint_2 = OpConstant %uint 2 + %float_0_25 = OpConstant %float 0.25 + %v2float = OpTypeVector %float 2 + %float_n4 = OpConstant %float -4 + %float_4 = OpConstant %float 4 +%float_n0_1875 = OpConstant %float -0.1875 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeFsrRcasConstants = OpTypeStruct %v2int %float +%_ptr_PushConstant_XeFsrRcasConstants = OpTypePointer PushConstant %XeFsrRcasConstants + %_ = OpVariable %_ptr_PushConstant_XeFsrRcasConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %uint_3 = OpConstant %uint 3 + %main = OpFunction %void None %3 + %5 = OpLabel + %655 = OpLoad %v4float %gl_FragCoord + %656 = OpVectorShuffle %v2float %655 %655 0 1 + %657 = OpConvertFToS %v2int %656 + %662 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %663 = OpLoad %v2int %662 + %664 = OpISub %v2int %657 %663 + %665 = OpBitcast %v2uint %664 + %668 = OpAccessChain %_ptr_PushConstant_float %_ %int_1 + %669 = OpLoad %float %668 + %670 = OpBitcast %uint %669 + %830 = OpBitcast %v2int %665 + %832 = OpIAdd %v2int %830 %144 + %1194 = OpLoad %121 %xe_texture + %1196 = OpImage %120 %1194 + %1197 = OpImageFetch %v4float %1196 %832 Lod %int_0 + %1199 = OpCompositeExtract %float %1197 0 + %1200 = OpCompositeExtract %float %1197 1 + %1201 = OpCompositeExtract %float %1197 2 + %836 = OpIAdd %v2int %830 %151 + %1207 = OpImage %120 %1194 + %1208 = OpImageFetch %v4float %1207 %836 Lod %int_0 + %1210 = OpCompositeExtract %float %1208 0 + %1211 = OpCompositeExtract %float %1208 1 + %1212 = OpCompositeExtract %float %1208 2 + %1218 = OpImage %120 %1194 + %1219 = OpImageFetch %v4float %1218 %830 Lod %int_0 + %1221 = OpCompositeExtract %float %1219 0 + %1222 = OpCompositeExtract %float %1219 1 + %1223 = OpCompositeExtract %float %1219 2 + %843 = OpIAdd %v2int %830 %164 + %1229 = OpImage %120 %1194 + %1230 = OpImageFetch %v4float %1229 %843 Lod %int_0 + %1232 = OpCompositeExtract %float %1230 0 + %1233 = OpCompositeExtract %float %1230 1 + %1234 = OpCompositeExtract %float %1230 2 + %847 = OpIAdd %v2int %830 %171 + %1240 = OpImage %120 %1194 + %1241 = OpImageFetch %v4float %1240 %847 Lod %int_0 + %1243 = OpCompositeExtract %float %1241 0 + %1244 = OpCompositeExtract %float %1241 1 + %1245 = OpCompositeExtract %float %1241 2 + %1371 = OpExtInst %float %1 FMin %1210 %1232 + %1372 = OpExtInst %float %1 FMin %1199 %1371 + %1007 = OpExtInst %float %1 FMin %1372 %1243 + %1378 = OpExtInst %float %1 FMin %1211 %1233 + %1379 = OpExtInst %float %1 FMin %1200 %1378 + %1013 = OpExtInst %float %1 FMin %1379 %1244 + %1385 = OpExtInst %float %1 FMin %1212 %1234 + %1386 = OpExtInst %float %1 FMin %1201 %1385 + %1019 = OpExtInst %float %1 FMin %1386 %1245 + %1392 = OpExtInst %float %1 FMax %1210 %1232 + %1393 = OpExtInst %float %1 FMax %1199 %1392 + %1025 = OpExtInst %float %1 FMax %1393 %1243 + %1399 = OpExtInst %float %1 FMax %1211 %1233 + %1400 = OpExtInst %float %1 FMax %1200 %1399 + %1031 = OpExtInst %float %1 FMax %1400 %1244 + %1406 = OpExtInst %float %1 FMax %1212 %1234 + %1407 = OpExtInst %float %1 FMax %1201 %1406 + %1037 = OpExtInst %float %1 FMax %1407 %1245 + %1040 = OpExtInst %float %1 FMin %1007 %1221 + %1416 = OpFDiv %float %float_0_25 %1025 + %1045 = OpFMul %float %1040 %1416 + %1048 = OpExtInst %float %1 FMin %1013 %1222 + %1428 = OpFDiv %float %float_0_25 %1031 + %1053 = OpFMul %float %1048 %1428 + %1056 = OpExtInst %float %1 FMin %1019 %1223 + %1440 = OpFDiv %float %float_0_25 %1037 + %1061 = OpFMul %float %1056 %1440 + %1066 = OpExtInst %float %1 FMax %1025 %1221 + %1067 = OpFSub %float %float_1 %1066 + %1070 = OpFMul %float %float_4 %1007 + %1073 = OpFAdd %float %1070 %float_n4 + %1452 = OpFDiv %float %float_1 %1073 + %1075 = OpFMul %float %1067 %1452 + %1080 = OpExtInst %float %1 FMax %1031 %1222 + %1081 = OpFSub %float %float_1 %1080 + %1084 = OpFMul %float %float_4 %1013 + %1087 = OpFAdd %float %1084 %float_n4 + %1464 = OpFDiv %float %float_1 %1087 + %1089 = OpFMul %float %1081 %1464 + %1094 = OpExtInst %float %1 FMax %1037 %1223 + %1095 = OpFSub %float %float_1 %1094 + %1098 = OpFMul %float %float_4 %1019 + %1101 = OpFAdd %float %1098 %float_n4 + %1476 = OpFDiv %float %float_1 %1101 + %1103 = OpFMul %float %1095 %1476 + %1105 = OpFNegate %float %1045 + %1107 = OpExtInst %float %1 FMax %1105 %1075 + %1109 = OpFNegate %float %1053 + %1111 = OpExtInst %float %1 FMax %1109 %1089 + %1113 = OpFNegate %float %1061 + %1115 = OpExtInst %float %1 FMax %1113 %1103 + %1488 = OpExtInst %float %1 FMax %1111 %1115 + %1489 = OpExtInst %float %1 FMax %1107 %1488 + %1122 = OpExtInst %float %1 FMin %1489 %float_0 + %1123 = OpExtInst %float %1 FMax %float_n0_1875 %1122 + %1126 = OpBitcast %float %670 + %1127 = OpFMul %float %1123 %1126 + %1130 = OpFMul %float %float_4 %1127 + %1132 = OpFAdd %float %1130 %float_1 + %1506 = OpBitcast %uint %1132 + %1507 = OpISub %uint %uint_2129764351 %1506 + %1508 = OpBitcast %float %1507 + %1511 = OpFNegate %float %1508 + %1513 = OpFMul %float %1511 %1132 + %1515 = OpFAdd %float %1513 %float_2 + %1516 = OpFMul %float %1508 %1515 + %1548 = OpFAdd %float %1199 %1210 + %1549 = OpFAdd %float %1548 %1243 + %1550 = OpFAdd %float %1549 %1232 + %1148 = OpFMul %float %1127 %1550 + %1150 = OpFAdd %float %1148 %1221 + %1152 = OpFMul %float %1150 %1516 + %1551 = OpFAdd %float %1200 %1211 + %1552 = OpFAdd %float %1551 %1244 + %1553 = OpFAdd %float %1552 %1233 + %1167 = OpFMul %float %1127 %1553 + %1169 = OpFAdd %float %1167 %1222 + %1171 = OpFMul %float %1169 %1516 + %1554 = OpFAdd %float %1201 %1212 + %1555 = OpFAdd %float %1554 %1245 + %1556 = OpFAdd %float %1555 %1234 + %1186 = OpFMul %float %1127 %1556 + %1188 = OpFAdd %float %1186 %1223 + %1190 = OpFMul %float %1188 %1516 + %688 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %688 %1152 + %690 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %690 %1171 + %692 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %692 %1190 + %694 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %694 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h new file mode 100644 index 000000000..e5e48733c --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h @@ -0,0 +1,109 @@ +// generated from `xb genspirv` +// source: guest_output_triangle_strip_rect.vert +const uint8_t guest_output_triangle_strip_rect_vert[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, + 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, + 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x58, 0x65, 0x54, 0x72, 0x69, 0x61, 0x6E, 0x67, 0x6C, 0x65, 0x53, 0x74, + 0x72, 0x69, 0x70, 0x52, 0x65, 0x63, 0x74, 0x43, 0x6F, 0x6E, 0x73, 0x74, + 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x72, 0x69, 0x61, 0x6E, 0x67, 0x6C, 0x65, 0x5F, 0x73, 0x74, 0x72, 0x69, + 0x70, 0x5F, 0x72, 0x65, 0x63, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, + 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, 0x72, 0x69, 0x61, 0x6E, + 0x67, 0x6C, 0x65, 0x5F, 0x73, 0x74, 0x72, 0x69, 0x70, 0x5F, 0x72, 0x65, + 0x63, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x56, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x20, 0x00, 0x04, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.spv new file mode 100644 index 000000000..3c2de3d30 Binary files /dev/null and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.txt new file mode 100644 index 000000000..e78174fa6 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.txt @@ -0,0 +1,74 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 47 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %_ %gl_VertexIndex + OpSource ESSL 310 + OpName %main "main" + OpName %gl_PerVertex "gl_PerVertex" + OpMemberName %gl_PerVertex 0 "gl_Position" + OpMemberName %gl_PerVertex 1 "gl_PointSize" + OpName %_ "" + OpName %XeTriangleStripRectConstants "XeTriangleStripRectConstants" + OpMemberName %XeTriangleStripRectConstants 0 "xe_triangle_strip_rect_offset" + OpMemberName %XeTriangleStripRectConstants 1 "xe_triangle_strip_rect_size" + OpName %__0 "" + OpName %gl_VertexIndex "gl_VertexIndex" + OpMemberDecorate %gl_PerVertex 0 BuiltIn Position + OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize + OpDecorate %gl_PerVertex Block + OpMemberDecorate %XeTriangleStripRectConstants 0 Offset 0 + OpMemberDecorate %XeTriangleStripRectConstants 1 Offset 8 + OpDecorate %XeTriangleStripRectConstants Block + OpDecorate %gl_VertexIndex BuiltIn VertexIndex + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%gl_PerVertex = OpTypeStruct %v4float %float +%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex + %_ = OpVariable %_ptr_Output_gl_PerVertex Output + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 + %v2float = OpTypeVector %float 2 +%XeTriangleStripRectConstants = OpTypeStruct %v2float %v2float +%_ptr_PushConstant_XeTriangleStripRectConstants = OpTypePointer PushConstant %XeTriangleStripRectConstants + %__0 = OpVariable %_ptr_PushConstant_XeTriangleStripRectConstants PushConstant +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float +%_ptr_Input_int = OpTypePointer Input %int +%gl_VertexIndex = OpVariable %_ptr_Input_int Input + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %uint_0 = OpConstant %uint 0 + %uint_1 = OpConstant %uint 1 + %29 = OpConstantComposite %v2uint %uint_0 %uint_1 + %int_1 = OpConstant %int 1 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %46 = OpConstantComposite %v2uint %uint_1 %uint_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %18 = OpAccessChain %_ptr_PushConstant_v2float %__0 %int_0 + %19 = OpLoad %v2float %18 + %22 = OpLoad %int %gl_VertexIndex + %24 = OpBitcast %uint %22 + %26 = OpCompositeConstruct %v2uint %24 %24 + %30 = OpShiftRightLogical %v2uint %26 %29 + %32 = OpBitwiseAnd %v2uint %30 %46 + %33 = OpConvertUToF %v2float %32 + %35 = OpAccessChain %_ptr_PushConstant_v2float %__0 %int_1 + %36 = OpLoad %v2float %35 + %37 = OpFMul %v2float %33 %36 + %38 = OpFAdd %v2float %19 %37 + %41 = OpCompositeExtract %float %38 0 + %42 = OpCompositeExtract %float %38 1 + %43 = OpCompositeConstruct %v4float %41 %42 %float_0 %float_1 + %45 = OpAccessChain %_ptr_Output_v4float %_ %int_0 + OpStore %45 %43 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h index 1ea709c75..1a1299653 100644 --- a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h @@ -32,9 +32,10 @@ const uint8_t immediate_vert[] = { 0x74, 0x74, 0x72, 0x5F, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x58, 0x65, 0x50, 0x75, 0x73, 0x68, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, - 0x6E, 0x74, 0x73, 0x00, 0x06, 0x00, 0x08, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, - 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, 0x6E, 0x76, 0x00, 0x00, 0x00, + 0x6E, 0x74, 0x73, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, + 0x69, 0x6E, 0x61, 0x74, 0x65, 0x5F, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5F, + 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.spv index ef72522c0..b2c19c5f0 100644 Binary files a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.spv and b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.spv differ diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.txt index fbc229b84..d5b18f232 100644 --- a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.txt +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.txt @@ -19,7 +19,7 @@ OpName %_ "" OpName %xe_attr_position "xe_attr_position" OpName %XePushConstants "XePushConstants" - OpMemberName %XePushConstants 0 "viewport_size_inv" + OpMemberName %XePushConstants 0 "xe_coordinate_space_size_inv" OpName %__0 "" OpDecorate %xe_var_texcoord Location 0 OpDecorate %xe_attr_texcoord Location 1 diff --git a/src/xenia/ui/shaders/dither_8bpc.xesli b/src/xenia/ui/shaders/dither_8bpc.xesli new file mode 100644 index 000000000..1f8b2946c --- /dev/null +++ b/src/xenia/ui/shaders/dither_8bpc.xesli @@ -0,0 +1,34 @@ +#ifndef XENIA_UI_SHADERS_DITHER_8BPC_XESLI_ +#define XENIA_UI_SHADERS_DITHER_8BPC_XESLI_ + +#include "xesl.xesli" + +#include "noise.xesli" + +xesl_static const float xe_dither_8bpc_noise[] = { + // The conversion to 8bpc in the fixed-function output-merger is done as + // floor(saturate(color) * 255.0 + 0.5). This dithering function effectively + // replaces that 0.5 offset, done for rounding to the nearest, with the noise. + // To do that, first, 0.5/255 needs to be subtracted from the color, and + // then the noise value `[0, 255/256] / 255` from xe_dither_8bpc_noise needs + // to be added. However, due to rounding (because division by 255.0 is + // inexact), subtracting 0.5/255 from exact 8-bit integer color values + // (including, for instance, 1.0, or 255/255) may result in the result being + // smaller than the original exact 8-bit value where the noise value is 0. So, + // remapping the noise to the `[0.5/256, 255.5/256] / 255` range. Another way + // of preventing rounding issues is doing it manually and returning only exact + // integer 8-bit color values divided by 255, but that would assume that the + // render target is specifically 8bpc, so it's better to avoid that in case + // the window system, for instance, provides a 10bpc render target (for which + // dithering is still done here for more consistency between displays, but + // some addition precision would still be desirable). + XeBlueNoise16x16Values0Until256(1.0 / 256.0 / 255.0, + (-0.5 + 0.5 / 256.0) / 255.0) +}; + +float XeDitherOffset8bpc(xesl_uint2 pixel_coord) { + pixel_coord &= 15u; + return xe_dither_8bpc_noise[pixel_coord.y * 16u + pixel_coord.x]; +} + +#endif // XENIA_UI_SHADERS_DITHER_8BPC_XESLI_ diff --git a/src/xenia/ui/shaders/guest_output_bilinear.frag b/src/xenia/ui/shaders/guest_output_bilinear.frag new file mode 100644 index 000000000..42fc74087 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear.frag @@ -0,0 +1,3 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#include "guest_output_bilinear.glsli" diff --git a/src/xenia/ui/shaders/guest_output_bilinear.glsli b/src/xenia/ui/shaders/guest_output_bilinear.glsli new file mode 100644 index 000000000..bffd8842e --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear.glsli @@ -0,0 +1,38 @@ +// At least #version 420. + +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +layout(push_constant) uniform XeBilinearConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) ivec2 xe_bilinear_output_offset; + layout(offset = 24) vec2 xe_bilinear_output_size_inv; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +void main() { + uvec2 pixel_coord = uvec2(ivec2(gl_FragCoord.xy) - xe_bilinear_output_offset); + // + 0.5 so the origin is at the pixel center, and at 1:1 the original pixel + // is taken. + // Interpolating the four colors in the perceptual space because doing it in + // linear space causes, in particular, bright text on a dark background to + // become too thick, and aliasing of bright parts on top of dark areas to be + // too apparent (4D5307E6 HUD, for example, mainly the edges of the + // multiplayer score bars). + xe_frag_color.rgb = + textureLod(xe_texture, + (vec2(pixel_coord) + 0.5) * xe_bilinear_output_size_inv, + 0.0).rgb; + #if XE_GUEST_OUTPUT_DITHER + // Clamping because on Vulkan, the surface may specify any format, including + // floating-point. + xe_frag_color.rgb = + clamp(xe_frag_color.rgb + XeDitherOffset8bpc(pixel_coord), + vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); + #endif // XE_GUEST_OUTPUT_DITHER + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_bilinear.hlsli b/src/xenia/ui/shaders/guest_output_bilinear.hlsli new file mode 100644 index 000000000..6685bfc29 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear.hlsli @@ -0,0 +1,31 @@ +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +cbuffer XeBilinearConstants : register(b0) { + int2 xe_bilinear_output_offset; + float2 xe_bilinear_output_size_inv; +}; + +Texture2D xe_texture : register(t0); +SamplerState xe_sampler_linear_clamp : register(s0); + +float4 main(float4 xe_position : SV_Position) : SV_Target { + uint2 pixel_coord = uint2(int2(xe_position.xy) - xe_bilinear_output_offset); + // + 0.5 so the origin is at the pixel center, and at 1:1 the original pixel + // is taken. + // Interpolating the four colors in the perceptual space because doing it in + // linear space causes, in particular, bright text on a dark background to + // become too thick, and aliasing of bright parts on top of dark areas to be + // too apparent (4D5307E6 HUD, for example, mainly the edges of the + // multiplayer score bars). + float3 color = xe_texture.SampleLevel( + xe_sampler_linear_clamp, + (float2(pixel_coord) + 0.5f) * xe_bilinear_output_size_inv, + 0.0f); + #if XE_GUEST_OUTPUT_DITHER + // Not clamping because a normalized format is explicitly requested on DXGI. + color += XeDitherOffset8bpc(pixel_coord); + #endif // XE_GUEST_OUTPUT_DITHER + return float4(color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_bilinear.ps.hlsl b/src/xenia/ui/shaders/guest_output_bilinear.ps.hlsl new file mode 100644 index 000000000..dd4e37b28 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear.ps.hlsl @@ -0,0 +1 @@ +#include "guest_output_bilinear.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_bilinear_dither.frag b/src/xenia/ui/shaders/guest_output_bilinear_dither.frag new file mode 100644 index 000000000..b78b5a9a4 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear_dither.frag @@ -0,0 +1,4 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_bilinear.glsli" diff --git a/src/xenia/ui/shaders/guest_output_bilinear_dither.ps.hlsl b/src/xenia/ui/shaders/guest_output_bilinear_dither.ps.hlsl new file mode 100644 index 000000000..13995e2bb --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear_dither.ps.hlsl @@ -0,0 +1,2 @@ +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_bilinear.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample.frag b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.frag new file mode 100644 index 000000000..a495b7bb4 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.frag @@ -0,0 +1,3 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#include "guest_output_ffx_cas_resample.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample.glsli b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.glsli new file mode 100644 index 000000000..21a35528e --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.glsli @@ -0,0 +1,57 @@ +// At least #version 420. + +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +layout(push_constant) uniform XeCasResampleConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) ivec2 xe_cas_output_offset; + // CasSetup const0.xy. + layout(offset = 24) vec2 xe_cas_input_output_size_ratio; + // CasSetup const1.x. + layout(offset = 32) float xe_cas_sharpness_post_setup; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +#define A_GPU 1 +#define A_GLSL 1 +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_a.h" +vec3 CasLoad(ivec2 p) { + return texelFetch(xe_texture, p, 0).rgb; +} +void CasInput(inout float r, inout float g, inout float b) { + // Linear conversion approximation as recommended in the CAS presentation. + r *= r; + g *= g; + b *= b; +} +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_cas.h" + +void main() { + uvec2 pixel_coord = uvec2(ivec2(gl_FragCoord.xy) - xe_cas_output_offset); + // CasSetup with smaller push constant usage. + uvec4 cas_const_0 = + uvec4(floatBitsToUint(xe_cas_input_output_size_ratio), + floatBitsToUint(0.5 * xe_cas_input_output_size_ratio - 0.5)); + uvec4 cas_const_1 = + uvec4(floatBitsToUint(xe_cas_sharpness_post_setup), + packHalf2x16(vec2(xe_cas_sharpness_post_setup, 0.0)), + floatBitsToUint(8.0 * xe_cas_input_output_size_ratio.x), 0u); + CasFilter(xe_frag_color.r, xe_frag_color.g, xe_frag_color.b, pixel_coord, + cas_const_0, cas_const_1, false); + // Linear conversion approximation as recommended in the CAS presentation. + xe_frag_color.rgb = sqrt(xe_frag_color.rgb); + #if XE_GUEST_OUTPUT_DITHER + // Clamping because on Vulkan, the surface may specify any format, including + // floating-point. + xe_frag_color.rgb = + clamp(xe_frag_color.rgb + XeDitherOffset8bpc(pixel_coord), + vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); + #endif // XE_GUEST_OUTPUT_DITHER + // Force alpha to 1 to make sure the surface won't be translucent. + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample.hlsli b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.hlsli new file mode 100644 index 000000000..843a00caa --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.hlsli @@ -0,0 +1,49 @@ +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +cbuffer XeCasResampleConstants : register(b0) { + int2 xe_cas_output_offset; + // CasSetup const0.xy. + float2 xe_cas_input_output_size_ratio; + // CasSetup const1.x. + float xe_cas_sharpness_post_setup; +}; + +Texture2D xe_texture : register(t0); + +#define A_GPU 1 +#define A_HLSL 1 +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_a.h" +float3 CasLoad(int2 p) { + return xe_texture.Load(int3(p, 0)).rgb; +} +void CasInput(inout float r, inout float g, inout float b) { + // Linear conversion approximation as recommended in the CAS presentation. + r *= r; + g *= g; + b *= b; +} +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_cas.h" + +float4 main(float4 xe_position : SV_Position) : SV_Target { + uint2 pixel_coord = uint2(int2(xe_position.xy) - xe_cas_output_offset); + // CasSetup with smaller root signature usage. + uint4 cas_const_0 = + uint4(asuint(xe_cas_input_output_size_ratio), + asuint(0.5f * xe_cas_input_output_size_ratio - 0.5f)); + uint4 cas_const_1 = + uint4(asuint(xe_cas_sharpness_post_setup), + f32tof16(xe_cas_sharpness_post_setup), + asuint(8.0f * xe_cas_input_output_size_ratio.x), 0u); + float3 cas_color; + CasFilter(cas_color.r, cas_color.g, cas_color.b, pixel_coord, cas_const_0, + cas_const_1, false); + // Linear conversion approximation as recommended in the CAS presentation. + cas_color = sqrt(cas_color); + #if XE_GUEST_OUTPUT_DITHER + // Not clamping because a normalized format is explicitly requested on DXGI. + cas_color += XeDitherOffset8bpc(pixel_coord); + #endif // XE_GUEST_OUTPUT_DITHER + return float4(cas_color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.ps.hlsl new file mode 100644 index 000000000..f970e5404 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.ps.hlsl @@ -0,0 +1 @@ +#include "guest_output_ffx_cas_resample.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.frag b/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.frag new file mode 100644 index 000000000..476c02dd3 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.frag @@ -0,0 +1,4 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_cas_resample.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.ps.hlsl new file mode 100644 index 000000000..4e76285b2 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.ps.hlsl @@ -0,0 +1,2 @@ +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_cas_resample.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.frag b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.frag new file mode 100644 index 000000000..059ea939d --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.frag @@ -0,0 +1,3 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#include "guest_output_ffx_cas_sharpen.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.glsli b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.glsli new file mode 100644 index 000000000..0cb6ea359 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.glsli @@ -0,0 +1,53 @@ +// At least #version 420. + +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +layout(push_constant) uniform XeCasSharpenConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) ivec2 xe_cas_output_offset; + // CasSetup const1.x. + layout(offset = 24) float xe_cas_sharpness_post_setup; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +#define A_GPU 1 +#define A_GLSL 1 +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_a.h" +vec3 CasLoad(ivec2 p) { + return texelFetch(xe_texture, p, 0).rgb; +} +void CasInput(inout float r, inout float g, inout float b) { + // Linear conversion approximation as recommended in the CAS presentation. + r *= r; + g *= g; + b *= b; +} +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_cas.h" + +void main() { + uvec2 pixel_coord = uvec2(ivec2(gl_FragCoord.xy) - xe_cas_output_offset); + // CasSetup with smaller push constant usage. + uvec4 cas_const_0 = floatBitsToUint(vec4(1.0, 1.0, 0.0, 0.0)); + uvec4 cas_const_1 = + uvec4(floatBitsToUint(xe_cas_sharpness_post_setup), + packHalf2x16(vec2(xe_cas_sharpness_post_setup, 0.0)), + floatBitsToUint(8.0), 0u); + CasFilter(xe_frag_color.r, xe_frag_color.g, xe_frag_color.b, pixel_coord, + cas_const_0, cas_const_1, false); + // Linear conversion approximation as recommended in the CAS presentation. + xe_frag_color.rgb = sqrt(xe_frag_color.rgb); + #if XE_GUEST_OUTPUT_DITHER + // Clamping because on Vulkan, the surface may specify any format, including + // floating-point. + xe_frag_color.rgb = + clamp(xe_frag_color.rgb + XeDitherOffset8bpc(pixel_coord), + vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); + #endif // XE_GUEST_OUTPUT_DITHER + // Force alpha to 1 to make sure the surface won't be translucent. + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.hlsli b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.hlsli new file mode 100644 index 000000000..0c47cc0e3 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.hlsli @@ -0,0 +1,44 @@ +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +cbuffer XeCasSharpenConstants : register(b0) { + int2 xe_cas_output_offset; + // CasSetup const1.x. + float xe_cas_sharpness_post_setup; +}; + +Texture2D xe_texture : register(t0); + +#define A_GPU 1 +#define A_HLSL 1 +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_a.h" +float3 CasLoad(int2 p) { + return xe_texture.Load(int3(p, 0)).rgb; +} +void CasInput(inout float r, inout float g, inout float b) { + // Linear conversion approximation as recommended in the CAS presentation. + r *= r; + g *= g; + b *= b; +} +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_cas.h" + +float4 main(float4 xe_position : SV_Position) : SV_Target { + uint2 pixel_coord = uint2(int2(xe_position.xy) - xe_cas_output_offset); + // CasSetup with smaller root signature usage. + uint4 cas_const_0 = asuint(float4(1.0f, 1.0f, 0.0f, 0.0f)); + uint4 cas_const_1 = + uint4(asuint(xe_cas_sharpness_post_setup), + f32tof16(xe_cas_sharpness_post_setup), asuint(8.0f), 0u); + float3 cas_color; + CasFilter(cas_color.r, cas_color.g, cas_color.b, pixel_coord, cas_const_0, + cas_const_1, true); + // Linear conversion approximation as recommended in the CAS presentation. + cas_color = sqrt(cas_color); + #if XE_GUEST_OUTPUT_DITHER + // Not clamping because a normalized format is explicitly requested on DXGI. + cas_color += XeDitherOffset8bpc(pixel_coord); + #endif // XE_GUEST_OUTPUT_DITHER + return float4(cas_color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.ps.hlsl new file mode 100644 index 000000000..3ff89fe34 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.ps.hlsl @@ -0,0 +1 @@ +#include "guest_output_ffx_cas_sharpen.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.frag b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.frag new file mode 100644 index 000000000..60c6b2f8b --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.frag @@ -0,0 +1,4 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_cas_sharpen.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.ps.hlsl new file mode 100644 index 000000000..3ad7b01b7 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.ps.hlsl @@ -0,0 +1,2 @@ +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_cas_sharpen.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.frag b/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.frag new file mode 100644 index 000000000..d5b2f1900 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.frag @@ -0,0 +1,38 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require + +layout(push_constant) uniform XeFsrEasuConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) vec2 xe_fsr_easu_input_output_size_ratio; + layout(offset = 24) vec2 xe_fsr_easu_input_size_inv; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +#define A_GPU 1 +#define A_GLSL 1 +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_a.h" +#define FSR_EASU_F 1 +vec4 FsrEasuRF(vec2 p) { return textureGather(xe_texture, p, 0); } +vec4 FsrEasuGF(vec2 p) { return textureGather(xe_texture, p, 1); } +vec4 FsrEasuBF(vec2 p) { return textureGather(xe_texture, p, 2); } +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h" + +void main() { + // FsrEasuCon with smaller push constant usage. + uvec4 easu_const_0 = + uvec4(floatBitsToUint(xe_fsr_easu_input_output_size_ratio), + floatBitsToUint(0.5 * xe_fsr_easu_input_output_size_ratio - 0.5)); + uvec4 easu_const_1 = floatBitsToUint(vec4(1.0, 1.0, 1.0, -1.0) * + xe_fsr_easu_input_size_inv.xyxy); + uvec4 easu_const_2 = floatBitsToUint(vec4(-1.0, 2.0, 1.0, 2.0) * + xe_fsr_easu_input_size_inv.xyxy); + uvec4 easu_const_3 = + uvec4(floatBitsToUint(0.0), + floatBitsToUint(4.0 * xe_fsr_easu_input_size_inv.y), 0u, 0u); + FsrEasuF(xe_frag_color.rgb, uvec2(gl_FragCoord.xy), easu_const_0, + easu_const_1, easu_const_2, easu_const_3); + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.ps.hlsl new file mode 100644 index 000000000..bd95e7a46 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.ps.hlsl @@ -0,0 +1,39 @@ +cbuffer XeFsrEasuConstants : register(b0) { + float2 xe_fsr_easu_input_output_size_ratio; + float2 xe_fsr_easu_input_size_inv; +}; + +Texture2D xe_texture : register(t0); +SamplerState xe_sampler_linear_clamp : register(s0); + +#define A_GPU 1 +#define A_HLSL 1 +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_a.h" +#define FSR_EASU_F 1 +float4 FsrEasuRF(float2 p) { + return xe_texture.GatherRed(xe_sampler_linear_clamp, p); +} +float4 FsrEasuGF(float2 p) { + return xe_texture.GatherGreen(xe_sampler_linear_clamp, p); +} +float4 FsrEasuBF(float2 p) { + return xe_texture.GatherBlue(xe_sampler_linear_clamp, p); +} +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h" + +float4 main(float4 xe_position : SV_Position) : SV_Target { + // FsrEasuCon with smaller root signature usage. + uint4 easu_const_0 = + uint4(asuint(xe_fsr_easu_input_output_size_ratio), + asuint(0.5f * xe_fsr_easu_input_output_size_ratio - 0.5f)); + uint4 easu_const_1 = + asuint(float4(1.0f, 1.0f, 1.0f, -1.0f) * xe_fsr_easu_input_size_inv.xyxy); + uint4 easu_const_2 = + asuint(float4(-1.0f, 2.0f, 1.0f, 2.0f) * xe_fsr_easu_input_size_inv.xyxy); + uint4 easu_const_3 = + uint4(asuint(0.0f), asuint(4.0f * xe_fsr_easu_input_size_inv.y), 0u, 0u); + float3 easu_color; + FsrEasuF(easu_color, uint2(xe_position.xy), easu_const_0, easu_const_1, + easu_const_2, easu_const_3); + return float4(easu_color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.frag b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.frag new file mode 100644 index 000000000..a5bb9f7af --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.frag @@ -0,0 +1,3 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#include "guest_output_ffx_fsr_rcas.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.glsli b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.glsli new file mode 100644 index 000000000..5c60cd8ea --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.glsli @@ -0,0 +1,45 @@ +// At least #version 420. + +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +layout(push_constant) uniform XeFsrRcasConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) ivec2 xe_fsr_rcas_output_offset; + // FsrRcasCon const0.x. + layout(offset = 24) float xe_fsr_rcas_sharpness_post_setup; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +#define A_GPU 1 +#define A_GLSL 1 +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_a.h" +#define FSR_RCAS_F 1 +vec4 FsrRcasLoadF(ivec2 p) { + return vec4(texelFetch(xe_texture, p, 0).rgb, 1.0); +} +void FsrRcasInputF(inout float r, inout float g, inout float b) {} +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h" + +void main() { + uvec2 pixel_coord = uvec2(ivec2(gl_FragCoord.xy) - xe_fsr_rcas_output_offset); + // FsrRcasCon with smaller push constant usage. + uvec4 rcas_const = + uvec4(floatBitsToUint(xe_fsr_rcas_sharpness_post_setup), + packHalf2x16(vec2(xe_fsr_rcas_sharpness_post_setup)), 0u, 0u); + FsrRcasF(xe_frag_color.r, xe_frag_color.g, xe_frag_color.b, pixel_coord, + rcas_const); + #if XE_GUEST_OUTPUT_DITHER + // Clamping because on Vulkan, the surface may specify any format, including + // floating-point. + xe_frag_color.rgb = + clamp(xe_frag_color.rgb + XeDitherOffset8bpc(pixel_coord), + vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); + #endif // XE_GUEST_OUTPUT_DITHER + // Force alpha to 1 to make sure the surface won't be translucent. + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.hlsli b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.hlsli new file mode 100644 index 000000000..c9bc3e7bf --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.hlsli @@ -0,0 +1,36 @@ +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +cbuffer XeFsrRcasConstants : register(b0) { + int2 xe_fsr_rcas_output_offset; + // FsrRcasCon const0.x. + float xe_fsr_rcas_sharpness_post_setup; +}; + +Texture2D xe_texture : register(t0); + +#define A_GPU 1 +#define A_HLSL 1 +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_a.h" +#define FSR_RCAS_F 1 +float4 FsrRcasLoadF(int2 p) { + return float4(xe_texture.Load(int3(p, 0)).rgb, 1.0f); +} +void FsrRcasInputF(inout float r, inout float g, inout float b) {} +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h" + +float4 main(float4 xe_position : SV_Position) : SV_Target { + uint2 pixel_coord = uint2(int2(xe_position.xy) - xe_fsr_rcas_output_offset); + // FsrRcasCon with smaller root signature usage. + uint4 rcas_const = + uint4(asuint(xe_fsr_rcas_sharpness_post_setup), + f32tof16(xe_fsr_rcas_sharpness_post_setup) * 0x00010001u, 0u, 0u); + float3 rcas_color; + FsrRcasF(rcas_color.r, rcas_color.g, rcas_color.b, pixel_coord, rcas_const); + #if XE_GUEST_OUTPUT_DITHER + // Not clamping because a normalized format is explicitly requested on DXGI. + rcas_color += XeDitherOffset8bpc(pixel_coord); + #endif // XE_GUEST_OUTPUT_DITHER + return float4(rcas_color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.ps.hlsl new file mode 100644 index 000000000..6133ff540 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.ps.hlsl @@ -0,0 +1 @@ +#include "guest_output_ffx_fsr_rcas.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.frag b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.frag new file mode 100644 index 000000000..2e0f18cb8 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.frag @@ -0,0 +1,4 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_fsr_rcas.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.ps.hlsl new file mode 100644 index 000000000..ed669fa64 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.ps.hlsl @@ -0,0 +1,2 @@ +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_fsr_rcas.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vert b/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vert new file mode 100644 index 000000000..5127c10ae --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vert @@ -0,0 +1,17 @@ +#version 310 es + +layout(push_constant) uniform XeTriangleStripRectConstants { + // If the layout is changed, update the base offset in all guest output + // fragment shaders! + vec2 xe_triangle_strip_rect_offset; + // Can be negative. + vec2 xe_triangle_strip_rect_size; +}; + +void main() { + // Passthrough - coordinate system differences are to be handled externally. + gl_Position = vec4(xe_triangle_strip_rect_offset + + vec2((uvec2(gl_VertexIndex) >> uvec2(0u, 1u)) & 1u) * + xe_triangle_strip_rect_size, + 0.0, 1.0); +} diff --git a/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vs.hlsl b/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vs.hlsl new file mode 100644 index 000000000..f265ac0a3 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vs.hlsl @@ -0,0 +1,14 @@ +cbuffer XeTriangleStripRectConstants : register(b0) { + float2 xe_triangle_strip_rect_offset; + // Can be negative. + float2 xe_triangle_strip_rect_size; +}; + +void main(uint xe_vertex_id : SV_VertexID, + out float4 xe_position : SV_Position) { + // Passthrough - coordinate system differences are to be handled externally. + xe_position = float4(xe_triangle_strip_rect_offset + + float2((xe_vertex_id >> uint2(0u, 1u)) & 1u) * + xe_triangle_strip_rect_size, + 0.0f, 1.0f); +} diff --git a/src/xenia/ui/shaders/immediate.vert b/src/xenia/ui/shaders/immediate.vert index 15328f108..ce84d6311 100644 --- a/src/xenia/ui/shaders/immediate.vert +++ b/src/xenia/ui/shaders/immediate.vert @@ -1,8 +1,7 @@ #version 310 es -precision highp float; layout(push_constant) uniform XePushConstants { - layout(offset = 0) vec2 viewport_size_inv; + vec2 xe_coordinate_space_size_inv; }; layout(location = 0) in vec2 xe_attr_position; @@ -15,6 +14,7 @@ layout(location = 1) out lowp vec4 xe_var_color; void main() { xe_var_texcoord = xe_attr_texcoord; xe_var_color = xe_attr_color; - gl_Position = vec4(xe_attr_position * viewport_size_inv * 2.0 - 1.0, 0.0, - 1.0); + gl_Position = + vec4(xe_attr_position * xe_coordinate_space_size_inv * 2.0 - 1.0, 0.0, + 1.0); } diff --git a/src/xenia/ui/shaders/immediate.vs.hlsl b/src/xenia/ui/shaders/immediate.vs.hlsl index d003fa030..0746fa4c4 100644 --- a/src/xenia/ui/shaders/immediate.vs.hlsl +++ b/src/xenia/ui/shaders/immediate.vs.hlsl @@ -1,5 +1,5 @@ cbuffer XeImmediateVertexConstants : register(b0) { - float2 xe_viewport_size_inv; + float2 xe_coordinate_space_size_inv; }; struct XeVertexShaderInput { @@ -17,7 +17,7 @@ struct XeVertexShaderOutput { XeVertexShaderOutput main(XeVertexShaderInput input) { XeVertexShaderOutput output; output.position = float4( - input.position * xe_viewport_size_inv * float2(2.0, -2.0) + + input.position * xe_coordinate_space_size_inv * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); output.texcoord = input.texcoord; output.color = input.color; diff --git a/src/xenia/ui/shaders/noise.xesli b/src/xenia/ui/shaders/noise.xesli new file mode 100644 index 000000000..4e3c897fa --- /dev/null +++ b/src/xenia/ui/shaders/noise.xesli @@ -0,0 +1,47 @@ +#ifndef XENIA_UI_SHADERS_NOISE_XESLI_ +#define XENIA_UI_SHADERS_NOISE_XESLI_ + +#define XeNoiseRow16(scale, offset, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, \ + va, vb, vc, vd, ve, vf) \ + v0 * scale + offset, v1 * scale + offset, v2 * scale + offset, \ + v3 * scale + offset, v4 * scale + offset, v5 * scale + offset, \ + v6 * scale + offset, v7 * scale + offset, v8 * scale + offset, \ + v9 * scale + offset, va * scale + offset, vb * scale + offset, \ + vc * scale + offset, vd * scale + offset, ve * scale + offset, \ + vf * scale + offset + +#define XeBlueNoise16x16Values0Until256(scale, offset) \ + XeNoiseRow16(scale, offset, 62, 185, 238, 26, 211, 88, 197, 37, 216, 161, \ + 207, 23, 166, 109, 200, 35), \ + XeNoiseRow16(scale, offset, 222, 92, 136, 49, 156, 59, 168, 96, 250, 56, \ + 121, 93, 221, 1, 82, 130), \ + XeNoiseRow16(scale, offset, 174, 42, 199, 108, 242, 18, 224, 125, 179, 8, \ + 147, 192, 51, 139, 235, 24), \ + XeNoiseRow16(scale, offset, 150, 249, 12, 71, 186, 138, 67, 28, 85, 212, 75, \ + 32, 245, 72, 183, 98), \ + XeNoiseRow16(scale, offset, 58, 118, 143, 220, 89, 115, 232, 194, 154, 114, \ + 231, 170, 123, 155, 20, 217), \ + XeNoiseRow16(scale, offset, 188, 84, 205, 33, 165, 4, 177, 43, 253, 19, 60, \ + 95, 6, 206, 106, 38), \ + XeNoiseRow16(scale, offset, 234, 7, 175, 68, 246, 53, 103, 134, 79, 204, \ + 132, 225, 191, 65, 254, 162), \ + XeNoiseRow16(scale, offset, 131, 46, 110, 228, 127, 148, 215, 13, 160, 50, \ + 178, 40, 145, 31, 119, 77), \ + XeNoiseRow16(scale, offset, 213, 153, 190, 97, 27, 195, 83, 237, 193, 100, \ + 244, 112, 87, 236, 182, 15), \ + XeNoiseRow16(scale, offset, 57, 243, 76, 11, 172, 63, 41, 116, 29, 149, 0, \ + 171, 22, 203, 157, 99), \ + XeNoiseRow16(scale, offset, 140, 30, 202, 133, 251, 219, 164, 135, 210, 90, \ + 64, 214, 142, 78, 39, 223), \ + XeNoiseRow16(scale, offset, 184, 104, 163, 54, 111, 91, 9, 240, 52, 176, \ + 230, 120, 48, 247, 129, 2), \ + XeNoiseRow16(scale, offset, 241, 81, 229, 16, 208, 141, 196, 80, 21, 107, \ + 159, 10, 189, 105, 173, 61), \ + XeNoiseRow16(scale, offset, 25, 126, 44, 180, 69, 34, 167, 122, 187, 255, \ + 36, 86, 226, 74, 209, 144), \ + XeNoiseRow16(scale, offset, 227, 201, 151, 102, 252, 218, 55, 233, 70, 137, \ + 198, 124, 146, 17, 45, 94), \ + XeNoiseRow16(scale, offset, 117, 5, 73, 169, 128, 3, 113, 152, 14, 101, 47, \ + 239, 66, 181, 248, 158) + +#endif // XENIA_UI_SHADERS_NOISE_XESLI_ diff --git a/src/xenia/ui/shaders/xesl.xesli b/src/xenia/ui/shaders/xesl.xesli new file mode 100644 index 000000000..d112c08a2 --- /dev/null +++ b/src/xenia/ui/shaders/xesl.xesli @@ -0,0 +1,45 @@ +#ifndef XENIA_UI_SHADERS_XESL_XESLI_ +#define XENIA_UI_SHADERS_XESL_XESLI_ + +// XESL_LANGUAGE_GLSL / HLSL are expected to be defined via compiler arguments. + +// Vectors. +#if XESL_LANGUAGE_GLSL + #define xesl_bool2 bvec2 + #define xesl_bool3 bvec3 + #define xesl_bool4 bvec4 + #define xesl_int2 ivec2 + #define xesl_int3 ivec3 + #define xesl_int4 ivec4 + #define xesl_uint2 uvec2 + #define xesl_uint3 uvec3 + #define xesl_uint4 uvec4 + #define xesl_float2 vec2 + #define xesl_float3 vec3 + #define xesl_float4 vec4 +#else + #define xesl_bool2 bool2 + #define xesl_bool3 bool3 + #define xesl_bool4 bool4 + #define xesl_int2 int2 + #define xesl_int3 int3 + #define xesl_int4 int4 + #define xesl_uint2 uint2 + #define xesl_uint3 uint3 + #define xesl_uint4 uint4 + #define xesl_float2 float2 + #define xesl_float3 float3 + #define xesl_float4 float4 +#endif // XESL_LANGUAGE_GLSL + +// Declarations. +#if XESL_LANGUAGE_HLSL + // HLSL requires static const to declare a constant in the global scope so it + // doesn't go to $Globals instead. + #define xesl_static static +#else + // GLSL requires just const to declare a constant in the global scope. + #define xesl_static +#endif // XESL_LANGUAGE_HLSL + +#endif // XENIA_UI_SHADERS_XESL_XESLI_ diff --git a/src/xenia/ui/surface.h b/src/xenia/ui/surface.h new file mode 100644 index 000000000..a37bcd8a3 --- /dev/null +++ b/src/xenia/ui/surface.h @@ -0,0 +1,83 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SURFACE_H_ +#define XENIA_UI_SURFACE_H_ + +#include + +#include "xenia/base/assert.h" + +namespace xe { +namespace ui { + +// Represents a surface that presenting can be performed to. +// Surface methods can be called only from the UI thread. + +class Surface { + public: + enum TypeIndex { + // Within one platform, the more preferable surface types are earlier in + // this enumeration, so xe::bit_scan_forward can be used to try creating + // surfaces of all types supported by both the graphics provider and the + // window. + // Android. + kTypeIndex_AndroidNativeWindow, + // GNU/Linux. + kTypeIndex_XcbWindow, + // Windows. + kTypeIndex_Win32Hwnd, + }; + using TypeFlags = uint32_t; + enum : TypeFlags { + kTypeFlag_AndroidNativeWindow = TypeFlags(1) + << kTypeIndex_AndroidNativeWindow, + kTypeFlag_XcbWindow = TypeFlags(1) << kTypeIndex_XcbWindow, + kTypeFlag_Win32Hwnd = TypeFlags(1) << kTypeIndex_Win32Hwnd, + }; + + Surface(const Surface& surface) = delete; + Surface& operator=(const Surface& surface) = delete; + virtual ~Surface() = default; + + virtual TypeIndex GetType() const = 0; + + // Returns the up-to-date size (and true), or zeros (and false) if not ready + // to open a presentation connection yet. The size preferably should be + // exactly the dimensions of the surface in physical pixels of the display + // (without stretching performed by the platform's composition), but even if + // stretching happens, it is required that surface pixels have 1:1 aspect + // ratio relatively to the physical display. + bool GetSize(uint32_t& width_out, uint32_t& height_out) { + // If any dimension is 0 (like, resized completely to zero in one direction, + // but not in another), the surface is zero-area - don't try to present to + // it. + uint32_t width, height; + if (!GetSizeImpl(width, height) || !width || !height) { + width_out = 0; + height_out = 0; + return false; + } + width_out = width; + height_out = height; + return true; + } + + protected: + Surface() = default; + + // Returns the up-to-date size in physical pixels (and true), or zeros (and + // optionally false) if not ready to open a presentation connection yet. + virtual bool GetSizeImpl(uint32_t& width_out, uint32_t& height_out) const = 0; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SURFACE_H_ diff --git a/src/xenia/ui/surface_android.cc b/src/xenia/ui/surface_android.cc new file mode 100644 index 000000000..f4ea30a39 --- /dev/null +++ b/src/xenia/ui/surface_android.cc @@ -0,0 +1,34 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/surface_android.h" + +#include + +namespace xe { +namespace ui { + +bool AndroidNativeWindowSurface::GetSizeImpl(uint32_t& width_out, + uint32_t& height_out) const { + if (!window_) { + return false; + } + int width = ANativeWindow_getWidth(window_); + int height = ANativeWindow_getHeight(window_); + // Negative value is returned in case of an error. + if (width <= 0 || height <= 0) { + return false; + } + width_out = uint32_t(width); + height_out = uint32_t(height); + return true; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/surface_android.h b/src/xenia/ui/surface_android.h new file mode 100644 index 000000000..7b9c684bd --- /dev/null +++ b/src/xenia/ui/surface_android.h @@ -0,0 +1,37 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SURFACE_ANDROID_H_ +#define XENIA_UI_SURFACE_ANDROID_H_ + +#include + +#include "xenia/ui/surface.h" + +namespace xe { +namespace ui { + +class AndroidNativeWindowSurface : public Surface { + public: + explicit AndroidNativeWindowSurface(ANativeWindow* window) + : window_(window) {} + TypeIndex GetType() const override { return kTypeIndex_AndroidNativeWindow; } + ANativeWindow* window() const { return window_; } + + protected: + bool GetSizeImpl(uint32_t& width_out, uint32_t& height_out) const override; + + private: + ANativeWindow* window_; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SURFACE_ANDROID_H_ diff --git a/src/xenia/ui/surface_gnulinux.cc b/src/xenia/ui/surface_gnulinux.cc new file mode 100644 index 000000000..9d3a990aa --- /dev/null +++ b/src/xenia/ui/surface_gnulinux.cc @@ -0,0 +1,31 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/surface_gnulinux.h" + +#include + +namespace xe { +namespace ui { + +bool XcbWindowSurface::GetSizeImpl(uint32_t& width_out, + uint32_t& height_out) const { + xcb_get_geometry_reply_t* reply = xcb_get_geometry_reply( + connection_, xcb_get_geometry(connection_, window_), nullptr); + if (!reply) { + return false; + } + width_out = reply->width; + height_out = reply->height; + std::free(reply); + return true; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/surface_gnulinux.h b/src/xenia/ui/surface_gnulinux.h new file mode 100644 index 000000000..44c6b98bc --- /dev/null +++ b/src/xenia/ui/surface_gnulinux.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SURFACE_GNULINUX_H_ +#define XENIA_UI_SURFACE_GNULINUX_H_ + +#include + +#include "xenia/ui/surface.h" + +namespace xe { +namespace ui { + +class XcbWindowSurface final : public Surface { + public: + explicit XcbWindowSurface(xcb_connection_t* connection, xcb_window_t window) + : connection_(connection), window_(window) {} + TypeIndex GetType() const override { return kTypeIndex_XcbWindow; } + xcb_connection_t* connection() const { return connection_; } + xcb_window_t window() const { return window_; } + + protected: + bool GetSizeImpl(uint32_t& width_out, uint32_t& height_out) const override; + + private: + xcb_connection_t* connection_; + xcb_window_t window_; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SURFACE_LINUX_H_ diff --git a/src/xenia/ui/surface_win.cc b/src/xenia/ui/surface_win.cc new file mode 100644 index 000000000..3cdc0e271 --- /dev/null +++ b/src/xenia/ui/surface_win.cc @@ -0,0 +1,35 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/surface_win.h" + +#include +#include + +#include "xenia/base/logging.h" + +namespace xe { +namespace ui { + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) +bool Win32HwndSurface::GetSizeImpl(uint32_t& width_out, + uint32_t& height_out) const { + RECT client_rect; + if (!GetClientRect(hwnd(), &client_rect)) { + return false; + } + width_out = uint32_t(std::max(client_rect.right - client_rect.left, LONG(0))); + height_out = + uint32_t(std::max(client_rect.bottom - client_rect.top, LONG(0))); + return true; +} +#endif + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/surface_win.h b/src/xenia/ui/surface_win.h new file mode 100644 index 000000000..68d6f0e5f --- /dev/null +++ b/src/xenia/ui/surface_win.h @@ -0,0 +1,45 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SURFACE_WIN_H_ +#define XENIA_UI_SURFACE_WIN_H_ + +#include +#include + +#include "xenia/ui/surface.h" + +// Must be included before Windows headers for things like NOMINMAX. +#include "xenia/base/platform_win.h" + +namespace xe { +namespace ui { + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) +class Win32HwndSurface final : public Surface { + public: + explicit Win32HwndSurface(HINSTANCE hinstance, HWND hwnd) + : hinstance_(hinstance), hwnd_(hwnd) {} + TypeIndex GetType() const override { return kTypeIndex_Win32Hwnd; } + HINSTANCE hinstance() const { return hinstance_; } + HWND hwnd() const { return hwnd_; } + + protected: + bool GetSizeImpl(uint32_t& width_out, uint32_t& height_out) const override; + + private: + HINSTANCE hinstance_; + HWND hwnd_; +}; +#endif + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SURFACE_WIN_H_ diff --git a/src/xenia/ui/ui_drawer.h b/src/xenia/ui/ui_drawer.h new file mode 100644 index 000000000..b5173dfd6 --- /dev/null +++ b/src/xenia/ui/ui_drawer.h @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_UI_DRAWER_H_ +#define XENIA_UI_UI_DRAWER_H_ + +#include + +namespace xe { +namespace ui { + +class UIDrawContext; + +class UIDrawer { + public: + // No preparation or finishing callbacks because drawers may register or + // unregister each other, so between the loops the list may be different. + + // The draw function may register or unregister drawers (and depending on the + // Z order the changes may or may not effect immediately). However, they must + // not perform any lifetime management of the presenter and of its connection + // to the surface. Ideally drawing should not be changing any state at all, + // however, in Dear ImGui, input is handled directly during drawing - any + // quitting or resizing, if done in the UI, must be deferred via something + // like WindowedAppContext::CallInUIThreadDeferred. + virtual void Draw(UIDrawContext& context) = 0; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_UI_DRAWER_H_ diff --git a/src/xenia/ui/ui_event.h b/src/xenia/ui/ui_event.h index 993eda672..4d5520782 100644 --- a/src/xenia/ui/ui_event.h +++ b/src/xenia/ui/ui_event.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -27,12 +27,40 @@ class UIEvent { Window* target() const { return target_; } private: - Window* target_ = nullptr; + Window* target_; +}; + +class UISetupEvent : public UIEvent { + public: + explicit UISetupEvent(Window* target = nullptr, bool is_initial_setup = false) + : UIEvent(target), is_initial_setup_(is_initial_setup) {} + + bool is_initial_setup() const { return is_initial_setup_; } + + private: + bool is_initial_setup_; +}; + +class MonitorUpdateEvent : public UISetupEvent { + public: + explicit MonitorUpdateEvent(Window* target, + bool old_monitor_potentially_disconnected, + bool is_initial_setup = false) + : UISetupEvent(target, is_initial_setup), + old_monitor_potentially_disconnected_( + old_monitor_potentially_disconnected) {} + + bool old_monitor_potentially_disconnected() const { + return old_monitor_potentially_disconnected_; + } + + private: + bool old_monitor_potentially_disconnected_; }; class FileDropEvent : public UIEvent { public: - FileDropEvent(Window* target, std::filesystem::path filename) + explicit FileDropEvent(Window* target, std::filesystem::path filename) : UIEvent(target), filename_(std::move(filename)) {} ~FileDropEvent() override = default; @@ -44,10 +72,10 @@ class FileDropEvent : public UIEvent { class KeyEvent : public UIEvent { public: - KeyEvent(Window* target, VirtualKey virtual_key, int repeat_count, - bool prev_state, bool modifier_shift_pressed, - bool modifier_ctrl_pressed, bool modifier_alt_pressed, - bool modifier_super_pressed) + explicit KeyEvent(Window* target, VirtualKey virtual_key, int repeat_count, + bool prev_state, bool modifier_shift_pressed, + bool modifier_ctrl_pressed, bool modifier_alt_pressed, + bool modifier_super_pressed) : UIEvent(target), virtual_key_(virtual_key), repeat_count_(repeat_count), @@ -96,9 +124,17 @@ class MouseEvent : public UIEvent { }; public: - MouseEvent(Window* target, Button button, int32_t x, int32_t y, - int32_t dx = 0, int32_t dy = 0) - : UIEvent(target), button_(button), x_(x), y_(y), dx_(dx), dy_(dy) {} + // Matching Windows WHEEL_DELTA. + static constexpr uint32_t kScrollPerDetent = 120; + + explicit MouseEvent(Window* target, Button button, int32_t x, int32_t y, + int32_t scroll_x = 0, int32_t scroll_y = 0) + : UIEvent(target), + button_(button), + x_(x), + y_(y), + scroll_x_(scroll_x), + scroll_y_(scroll_y) {} ~MouseEvent() override = default; bool is_handled() const { return handled_; } @@ -107,16 +143,17 @@ class MouseEvent : public UIEvent { Button button() const { return button_; } int32_t x() const { return x_; } int32_t y() const { return y_; } - int32_t dx() const { return dx_; } - int32_t dy() const { return dy_; } + int32_t scroll_x() const { return scroll_x_; } + int32_t scroll_y() const { return scroll_y_; } private: bool handled_ = false; Button button_; int32_t x_ = 0; int32_t y_ = 0; - int32_t dx_ = 0; - int32_t dy_ = 0; + int32_t scroll_x_ = 0; + // Positive is up (away from the user), negative is down (towards the user). + int32_t scroll_y_ = 0; }; } // namespace ui diff --git a/src/xenia/ui/vulkan/functions/device_1_0.inc b/src/xenia/ui/vulkan/functions/device_1_0.inc new file mode 100644 index 000000000..f0811fcea --- /dev/null +++ b/src/xenia/ui/vulkan/functions/device_1_0.inc @@ -0,0 +1,68 @@ +// Vulkan 1.0 core device functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkAllocateCommandBuffers) +XE_UI_VULKAN_FUNCTION(vkAllocateDescriptorSets) +XE_UI_VULKAN_FUNCTION(vkAllocateMemory) +XE_UI_VULKAN_FUNCTION(vkBeginCommandBuffer) +XE_UI_VULKAN_FUNCTION(vkBindBufferMemory) +XE_UI_VULKAN_FUNCTION(vkBindImageMemory) +XE_UI_VULKAN_FUNCTION(vkCmdBeginRenderPass) +XE_UI_VULKAN_FUNCTION(vkCmdBindDescriptorSets) +XE_UI_VULKAN_FUNCTION(vkCmdBindIndexBuffer) +XE_UI_VULKAN_FUNCTION(vkCmdBindPipeline) +XE_UI_VULKAN_FUNCTION(vkCmdBindVertexBuffers) +XE_UI_VULKAN_FUNCTION(vkCmdClearAttachments) +XE_UI_VULKAN_FUNCTION(vkCmdClearColorImage) +XE_UI_VULKAN_FUNCTION(vkCmdCopyBuffer) +XE_UI_VULKAN_FUNCTION(vkCmdCopyBufferToImage) +XE_UI_VULKAN_FUNCTION(vkCmdCopyImageToBuffer) +XE_UI_VULKAN_FUNCTION(vkCmdDraw) +XE_UI_VULKAN_FUNCTION(vkCmdDrawIndexed) +XE_UI_VULKAN_FUNCTION(vkCmdEndRenderPass) +XE_UI_VULKAN_FUNCTION(vkCmdPipelineBarrier) +XE_UI_VULKAN_FUNCTION(vkCmdPushConstants) +XE_UI_VULKAN_FUNCTION(vkCmdSetScissor) +XE_UI_VULKAN_FUNCTION(vkCmdSetViewport) +XE_UI_VULKAN_FUNCTION(vkCreateBuffer) +XE_UI_VULKAN_FUNCTION(vkCreateCommandPool) +XE_UI_VULKAN_FUNCTION(vkCreateDescriptorPool) +XE_UI_VULKAN_FUNCTION(vkCreateDescriptorSetLayout) +XE_UI_VULKAN_FUNCTION(vkCreateFence) +XE_UI_VULKAN_FUNCTION(vkCreateFramebuffer) +XE_UI_VULKAN_FUNCTION(vkCreateGraphicsPipelines) +XE_UI_VULKAN_FUNCTION(vkCreateImage) +XE_UI_VULKAN_FUNCTION(vkCreateImageView) +XE_UI_VULKAN_FUNCTION(vkCreatePipelineLayout) +XE_UI_VULKAN_FUNCTION(vkCreateRenderPass) +XE_UI_VULKAN_FUNCTION(vkCreateSampler) +XE_UI_VULKAN_FUNCTION(vkCreateSemaphore) +XE_UI_VULKAN_FUNCTION(vkCreateShaderModule) +XE_UI_VULKAN_FUNCTION(vkDestroyBuffer) +XE_UI_VULKAN_FUNCTION(vkDestroyCommandPool) +XE_UI_VULKAN_FUNCTION(vkDestroyDescriptorPool) +XE_UI_VULKAN_FUNCTION(vkDestroyDescriptorSetLayout) +XE_UI_VULKAN_FUNCTION(vkDestroyFence) +XE_UI_VULKAN_FUNCTION(vkDestroyFramebuffer) +XE_UI_VULKAN_FUNCTION(vkDestroyImage) +XE_UI_VULKAN_FUNCTION(vkDestroyImageView) +XE_UI_VULKAN_FUNCTION(vkDestroyPipeline) +XE_UI_VULKAN_FUNCTION(vkDestroyPipelineLayout) +XE_UI_VULKAN_FUNCTION(vkDestroyRenderPass) +XE_UI_VULKAN_FUNCTION(vkDestroySampler) +XE_UI_VULKAN_FUNCTION(vkDestroySemaphore) +XE_UI_VULKAN_FUNCTION(vkDestroyShaderModule) +XE_UI_VULKAN_FUNCTION(vkEndCommandBuffer) +XE_UI_VULKAN_FUNCTION(vkFlushMappedMemoryRanges) +XE_UI_VULKAN_FUNCTION(vkFreeMemory) +XE_UI_VULKAN_FUNCTION(vkGetBufferMemoryRequirements) +XE_UI_VULKAN_FUNCTION(vkGetDeviceQueue) +XE_UI_VULKAN_FUNCTION(vkGetFenceStatus) +XE_UI_VULKAN_FUNCTION(vkGetImageMemoryRequirements) +XE_UI_VULKAN_FUNCTION(vkMapMemory) +XE_UI_VULKAN_FUNCTION(vkResetCommandPool) +XE_UI_VULKAN_FUNCTION(vkResetDescriptorPool) +XE_UI_VULKAN_FUNCTION(vkResetFences) +XE_UI_VULKAN_FUNCTION(vkQueueBindSparse) +XE_UI_VULKAN_FUNCTION(vkQueueSubmit) +XE_UI_VULKAN_FUNCTION(vkUnmapMemory) +XE_UI_VULKAN_FUNCTION(vkUpdateDescriptorSets) +XE_UI_VULKAN_FUNCTION(vkWaitForFences) diff --git a/src/xenia/ui/vulkan/functions/device_khr_swapchain.inc b/src/xenia/ui/vulkan/functions/device_khr_swapchain.inc new file mode 100644 index 000000000..435d88a82 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/device_khr_swapchain.inc @@ -0,0 +1,6 @@ +// VK_KHR_swapchain functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkAcquireNextImageKHR) +XE_UI_VULKAN_FUNCTION(vkCreateSwapchainKHR) +XE_UI_VULKAN_FUNCTION(vkDestroySwapchainKHR) +XE_UI_VULKAN_FUNCTION(vkGetSwapchainImagesKHR) +XE_UI_VULKAN_FUNCTION(vkQueuePresentKHR) diff --git a/src/xenia/ui/vulkan/functions/instance_1_0.inc b/src/xenia/ui/vulkan/functions/instance_1_0.inc new file mode 100644 index 000000000..cdeb97209 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_1_0.inc @@ -0,0 +1,10 @@ +// Vulkan 1.0 core instance functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkCreateDevice) +XE_UI_VULKAN_FUNCTION(vkDestroyDevice) +XE_UI_VULKAN_FUNCTION(vkEnumerateDeviceExtensionProperties) +XE_UI_VULKAN_FUNCTION(vkEnumeratePhysicalDevices) +XE_UI_VULKAN_FUNCTION(vkGetDeviceProcAddr) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceFeatures) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceMemoryProperties) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceProperties) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties) diff --git a/src/xenia/ui/vulkan/functions/instance_ext_debug_utils.inc b/src/xenia/ui/vulkan/functions/instance_ext_debug_utils.inc new file mode 100644 index 000000000..c0c9df20c --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_ext_debug_utils.inc @@ -0,0 +1,4 @@ +// VK_EXT_debug_utils functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkCreateDebugUtilsMessengerEXT) +XE_UI_VULKAN_FUNCTION(vkDestroyDebugUtilsMessengerEXT) +XE_UI_VULKAN_FUNCTION(vkSetDebugUtilsObjectNameEXT) diff --git a/src/xenia/ui/vulkan/functions/instance_khr_android_surface.inc b/src/xenia/ui/vulkan/functions/instance_khr_android_surface.inc new file mode 100644 index 000000000..7449ac2d1 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_khr_android_surface.inc @@ -0,0 +1,2 @@ +// VK_KHR_android_surface functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkCreateAndroidSurfaceKHR) diff --git a/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc b/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc new file mode 100644 index 000000000..05b2fe800 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc @@ -0,0 +1,4 @@ +// VK_KHR_get_physical_device_properties2 functions used in Xenia. +// Promoted to Vulkan 1.1 core. +XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetPhysicalDeviceProperties2KHR, + vkGetPhysicalDeviceProperties2) diff --git a/src/xenia/ui/vulkan/functions/instance_khr_surface.inc b/src/xenia/ui/vulkan/functions/instance_khr_surface.inc new file mode 100644 index 000000000..ca3efdebf --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_khr_surface.inc @@ -0,0 +1,6 @@ +// VK_KHR_surface functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkDestroySurfaceKHR) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR) diff --git a/src/xenia/ui/vulkan/functions/instance_khr_win32_surface.inc b/src/xenia/ui/vulkan/functions/instance_khr_win32_surface.inc new file mode 100644 index 000000000..9b6d673d5 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_khr_win32_surface.inc @@ -0,0 +1,3 @@ +// VK_KHR_win32_surface functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkCreateWin32SurfaceKHR) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceWin32PresentationSupportKHR) diff --git a/src/xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc b/src/xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc new file mode 100644 index 000000000..4faa37b75 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc @@ -0,0 +1,2 @@ +// VK_KHR_xcb_surface functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkCreateXcbSurfaceKHR) diff --git a/src/xenia/ui/vulkan/premake5.lua b/src/xenia/ui/vulkan/premake5.lua index ca0a8a8c1..cd100eee1 100644 --- a/src/xenia/ui/vulkan/premake5.lua +++ b/src/xenia/ui/vulkan/premake5.lua @@ -11,6 +11,7 @@ project("xenia-ui-vulkan") "xenia-ui", }) local_platform_files() + local_platform_files("functions") files({ "../shaders/bytecode/vulkan_spirv/*.h", }) @@ -35,3 +36,10 @@ project("xenia-ui-window-vulkan-demo") resincludedirs({ project_root, }) + + filter("platforms:Linux") + links({ + "X11", + "xcb", + "X11-xcb", + }) diff --git a/src/xenia/ui/vulkan/vulkan_context.cc b/src/xenia/ui/vulkan/vulkan_context.cc deleted file mode 100644 index 0d89bee35..000000000 --- a/src/xenia/ui/vulkan/vulkan_context.cc +++ /dev/null @@ -1,1017 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/vulkan/vulkan_context.h" - -#include -#include -#include -#include - -#include "xenia/base/assert.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/platform.h" -#include "xenia/ui/vulkan/vulkan_immediate_drawer.h" -#include "xenia/ui/vulkan/vulkan_provider.h" -#include "xenia/ui/vulkan/vulkan_util.h" -#include "xenia/ui/window.h" - -#if XE_PLATFORM_ANDROID -#include -#elif XE_PLATFORM_WIN32 -#include "xenia/base/platform_win.h" -#endif - -namespace xe { -namespace ui { -namespace vulkan { - -VulkanContext::VulkanContext(VulkanProvider* provider, Window* target_window) - : GraphicsContext(provider, target_window) {} - -VulkanContext::~VulkanContext() { Shutdown(); } - -bool VulkanContext::Initialize() { - context_lost_ = false; - - if (!target_window_) { - return true; - } - - const VulkanProvider& provider = GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - - VkFenceCreateInfo fence_create_info; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_create_info.pNext = nullptr; - fence_create_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - VkSemaphoreCreateInfo semaphore_create_info; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - semaphore_create_info.pNext = nullptr; - semaphore_create_info.flags = 0; - - VkCommandPoolCreateInfo command_pool_create_info; - command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - command_pool_create_info.pNext = nullptr; - command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; - command_pool_create_info.queueFamilyIndex = - provider.queue_family_graphics_compute(); - - VkCommandBufferAllocateInfo command_buffer_allocate_info; - command_buffer_allocate_info.sType = - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.pNext = nullptr; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - command_buffer_allocate_info.commandBufferCount = 1; - - for (uint32_t i = 0; i < kSwapchainMaxImageCount; ++i) { - SwapSubmission& submission = swap_submissions_[i]; - if (dfn.vkCreateFence(device, &fence_create_info, nullptr, - &submission.fence) != VK_SUCCESS) { - XELOGE("Failed to create the Vulkan composition fences"); - Shutdown(); - return false; - } - if (dfn.vkCreateSemaphore(device, &semaphore_create_info, nullptr, - &submission.image_acquisition_semaphore) != - VK_SUCCESS) { - XELOGE( - "Failed to create the Vulkan swap chain image acquisition " - "semaphores"); - Shutdown(); - return false; - } - if (dfn.vkCreateSemaphore(device, &semaphore_create_info, nullptr, - &submission.render_completion_semaphore) != - VK_SUCCESS) { - XELOGE( - "Failed to create the Vulkan swap chain rendering completion " - "semaphores"); - Shutdown(); - return false; - } - if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr, - &submission.command_pool) != VK_SUCCESS) { - XELOGE("Failed to create the Vulkan composition command pools"); - Shutdown(); - return false; - } - command_buffer_allocate_info.commandPool = submission.command_pool; - if (dfn.vkAllocateCommandBuffers(device, &command_buffer_allocate_info, - &submission.command_buffer) != - VK_SUCCESS) { - XELOGE("Failed to allocate the Vulkan composition command buffers"); - Shutdown(); - return false; - } - } - - immediate_drawer_ = std::make_unique(*this); - if (!immediate_drawer_->Initialize()) { - Shutdown(); - return false; - } - - swap_swapchain_or_surface_recreation_needed_ = true; - - return true; -} - -void VulkanContext::Shutdown() { - if (!target_window_) { - return; - } - - AwaitAllSwapSubmissionsCompletion(); - - immediate_drawer_.reset(); - - const VulkanProvider& provider = GetVulkanProvider(); - const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); - VkInstance instance = provider.instance(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - - swap_swapchain_image_current_ = UINT32_MAX; - DestroySwapchainFramebuffers(); - util::DestroyAndNullHandle(dfn.vkDestroySwapchainKHR, device, - swap_swapchain_); - util::DestroyAndNullHandle(dfn.vkDestroyRenderPass, device, - swap_render_pass_); - util::DestroyAndNullHandle(ifn.vkDestroySurfaceKHR, instance, swap_surface_); - swap_swapchain_or_surface_recreation_needed_ = false; - - swap_submission_completed_ = 0; - swap_submission_current_ = 1; - for (uint32_t i = 0; i < kSwapchainMaxImageCount; ++i) { - if (i < swap_setup_command_buffers_allocated_count_) { - dfn.vkDestroyCommandPool(device, swap_setup_command_buffers_[i].first, - nullptr); - } - SwapSubmission& submission = swap_submissions_[i]; - submission.setup_command_buffer_index = UINT32_MAX; - util::DestroyAndNullHandle(dfn.vkDestroyCommandPool, device, - submission.command_pool); - util::DestroyAndNullHandle(dfn.vkDestroySemaphore, device, - submission.render_completion_semaphore); - util::DestroyAndNullHandle(dfn.vkDestroySemaphore, device, - submission.image_acquisition_semaphore); - util::DestroyAndNullHandle(dfn.vkDestroyFence, device, submission.fence); - } - swap_setup_command_buffers_free_bits_ = 0; - swap_setup_command_buffers_allocated_count_ = 0; -} - -ImmediateDrawer* VulkanContext::immediate_drawer() { - return immediate_drawer_.get(); -} - -bool VulkanContext::WasLost() { return context_lost_; } - -bool VulkanContext::BeginSwap() { - if (!target_window_ || context_lost_) { - return false; - } - - const VulkanProvider& provider = GetVulkanProvider(); - const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); - VkPhysicalDevice physical_device = provider.physical_device(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - - uint32_t window_width = uint32_t(target_window_->scaled_width()); - uint32_t window_height = uint32_t(target_window_->scaled_height()); - if (swap_swapchain_ != VK_NULL_HANDLE) { - // Check if need to resize. - assert_true(swap_surface_ != VK_NULL_HANDLE); - // Win32 has minImageExtent == maxImageExtent == currentExtent, so the - // capabilities need to be requested every time they are needed. - VkSurfaceCapabilitiesKHR surface_capabilities; - if (ifn.vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - physical_device, swap_surface_, &surface_capabilities) == - VK_SUCCESS) { - if (swap_swapchain_extent_.width != - xe::clamp(window_width, surface_capabilities.minImageExtent.width, - surface_capabilities.maxImageExtent.width) || - swap_swapchain_extent_.height != - xe::clamp(window_height, - surface_capabilities.minImageExtent.height, - surface_capabilities.maxImageExtent.height)) { - swap_swapchain_or_surface_recreation_needed_ = true; - } - } - } - - // If the swap chain turns out to be out of date, try to recreate it on the - // second attempt (to avoid skipping the frame entirely in this case). - for (uint32_t attempt = 0; attempt < 2; ++attempt) { - if (swap_swapchain_or_surface_recreation_needed_) { - // If recreation fails, don't retry until some change happens. - swap_swapchain_or_surface_recreation_needed_ = false; - - AwaitAllSwapSubmissionsCompletion(); - - uint32_t queue_family_graphics_compute = - provider.queue_family_graphics_compute(); - - if (swap_surface_ == VK_NULL_HANDLE) { - assert_true(swap_swapchain_ == VK_NULL_HANDLE); - assert_true(swap_swapchain_image_views_.empty()); - assert_true(swap_swapchain_framebuffers_.empty()); - - VkInstance instance = provider.instance(); - - VkResult surface_create_result; -#if XE_PLATFORM_ANDROID - VkAndroidSurfaceCreateInfoKHR surface_create_info; - surface_create_info.window = - reinterpret_cast(target_window_->native_handle()); - if (!surface_create_info.window) { - // The activity is in background - try again when the window is - // created. - return false; - } - surface_create_info.sType = - VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; - surface_create_info.pNext = nullptr; - surface_create_info.flags = 0; - surface_create_result = ifn.vkCreateAndroidSurfaceKHR( - instance, &surface_create_info, nullptr, &swap_surface_); -#elif XE_PLATFORM_WIN32 - VkWin32SurfaceCreateInfoKHR surface_create_info; - surface_create_info.sType = - VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - surface_create_info.pNext = nullptr; - surface_create_info.flags = 0; - surface_create_info.hinstance = reinterpret_cast( - target_window_->native_platform_handle()); - surface_create_info.hwnd = - reinterpret_cast(target_window_->native_handle()); - surface_create_result = ifn.vkCreateWin32SurfaceKHR( - instance, &surface_create_info, nullptr, &swap_surface_); -#else -#error No Vulkan surface creation for the target platform. -#endif - if (surface_create_result != VK_SUCCESS) { - XELOGE("Failed to create a Vulkan surface"); - return false; - } - - // FIXME(Triang3l): Allow a separate queue for present - see - // vulkan_provider.cc for details. - VkBool32 surface_supported; - if (ifn.vkGetPhysicalDeviceSurfaceSupportKHR( - physical_device, queue_family_graphics_compute, swap_surface_, - &surface_supported) != VK_SUCCESS || - !surface_supported) { - XELOGE( - "The Vulkan graphics and compute queue doesn't support " - "presentation"); - ifn.vkDestroySurfaceKHR(instance, swap_surface_, nullptr); - swap_surface_ = VK_NULL_HANDLE; - return false; - } - - // Choose an SDR format, 8.8.8.8 preferred, or if not available, any - // supported. Windows and GNU/Linux use B8G8R8A8, Android uses R8G8B8A8. - std::vector surface_formats; - VkResult surface_formats_get_result; - for (;;) { - uint32_t surface_format_count = uint32_t(surface_formats.size()); - bool surface_formats_was_empty = !surface_format_count; - surface_formats_get_result = ifn.vkGetPhysicalDeviceSurfaceFormatsKHR( - physical_device, swap_surface_, &surface_format_count, - surface_formats_was_empty ? nullptr : surface_formats.data()); - // If the original surface format count was 0 (first call), SUCCESS is - // returned, not INCOMPLETE. - if (surface_formats_get_result == VK_SUCCESS || - surface_formats_get_result == VK_INCOMPLETE) { - surface_formats.resize(surface_format_count); - if (surface_formats_get_result == VK_SUCCESS && - (!surface_formats_was_empty || !surface_format_count)) { - break; - } - } else { - break; - } - } - if (surface_formats_get_result != VK_SUCCESS || - surface_formats.empty()) { - XELOGE("Failed to get Vulkan surface formats"); - ifn.vkDestroySurfaceKHR(instance, swap_surface_, nullptr); - swap_surface_ = VK_NULL_HANDLE; - return false; - } - VkSurfaceFormatKHR surface_format; - if (surface_formats.size() == 1 && - surface_formats[0].format == VK_FORMAT_UNDEFINED) { -#if XE_PLATFORM_ANDROID - surface_format.format = VK_FORMAT_R8G8B8A8_UNORM; -#else - surface_format.format = VK_FORMAT_B8G8R8A8_UNORM; -#endif - surface_format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - } else { - surface_format = surface_formats.front(); - for (const VkSurfaceFormatKHR& surface_format_current : - surface_formats) { - if (surface_format_current.format == VK_FORMAT_B8G8R8A8_UNORM || - surface_format_current.format == VK_FORMAT_R8G8B8A8_UNORM || - surface_format_current.format == - VK_FORMAT_A8B8G8R8_UNORM_PACK32) { - surface_format = surface_format_current; - break; - } - } - } - if (swap_surface_format_.format != surface_format.format) { - util::DestroyAndNullHandle(dfn.vkDestroyRenderPass, device, - swap_render_pass_); - } - swap_surface_format_ = surface_format; - - // Prefer a low-latency present mode because emulation is done on the - // same queue, ordered by the decreasing amount of tearing, fall back to - // FIFO if no other options. - swap_surface_present_mode_ = VK_PRESENT_MODE_FIFO_KHR; - std::vector surface_present_modes; - VkResult surface_present_modes_get_result; - for (;;) { - uint32_t surface_present_mode_count = - uint32_t(surface_present_modes.size()); - bool surface_present_modes_was_empty = !surface_present_mode_count; - surface_present_modes_get_result = - ifn.vkGetPhysicalDeviceSurfacePresentModesKHR( - physical_device, swap_surface_, &surface_present_mode_count, - surface_present_modes_was_empty - ? nullptr - : surface_present_modes.data()); - // If the original surface present mode count was 0 (first call), - // SUCCESS is returned, not INCOMPLETE. - if (surface_present_modes_get_result == VK_SUCCESS || - surface_present_modes_get_result == VK_INCOMPLETE) { - surface_present_modes.resize(surface_present_mode_count); - if (surface_present_modes_get_result == VK_SUCCESS && - (!surface_present_modes_was_empty || - !surface_present_mode_count)) { - break; - } - } else { - break; - } - } - if (surface_present_modes_get_result == VK_SUCCESS) { - static const VkPresentModeKHR present_modes_preferred[] = { - VK_PRESENT_MODE_MAILBOX_KHR, - VK_PRESENT_MODE_FIFO_RELAXED_KHR, - VK_PRESENT_MODE_IMMEDIATE_KHR, - }; - for (size_t i = 0; i < xe::countof(present_modes_preferred); ++i) { - VkPresentModeKHR present_mode_preferred = - present_modes_preferred[i]; - if (std::find(surface_present_modes.cbegin(), - surface_present_modes.cend(), - present_mode_preferred) != - surface_present_modes.cend()) { - swap_surface_present_mode_ = present_mode_preferred; - break; - } - } - } - } - - // Recreate the swap chain unconditionally because a request was made. - // The old swapchain will be retired even if vkCreateSwapchainKHR fails, - // so destroy the framebuffers and the image views unconditionally. - // If anything fails before the vkCreateSwapchainKHR call, also destroy - // the swapchain to fulfill the request. - // It was safe to handle errors while creating the surface without caring - // about destroying the swapchain, because there can't be swapchain when - // there is no surface. - DestroySwapchainFramebuffers(); - // Win32 has minImageExtent == maxImageExtent == currentExtent, so the - // capabilities need to be requested every time they are needed. - VkSurfaceCapabilitiesKHR surface_capabilities; - if (ifn.vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - physical_device, swap_surface_, &surface_capabilities) != - VK_SUCCESS) { - XELOGE("Failed to get Vulkan surface capabilities"); - util::DestroyAndNullHandle(dfn.vkDestroySwapchainKHR, device, - swap_swapchain_); - return false; - } - // TODO(Triang3l): Support rotated transforms. - if (!(surface_capabilities.supportedTransforms & - VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)) { - XELOGE("The Vulkan surface doesn't support identity transform"); - util::DestroyAndNullHandle(dfn.vkDestroySwapchainKHR, device, - swap_swapchain_); - return false; - } - VkSwapchainCreateInfoKHR swapchain_create_info; - swapchain_create_info.imageExtent.width = - xe::clamp(window_width, surface_capabilities.minImageExtent.width, - surface_capabilities.maxImageExtent.width); - swapchain_create_info.imageExtent.height = - xe::clamp(window_height, surface_capabilities.minImageExtent.height, - surface_capabilities.maxImageExtent.height); - if (!swapchain_create_info.imageExtent.width || - !swapchain_create_info.imageExtent.height) { - // Everything else is fine with the surface, but the window is too - // small, try again when the window may be resized (won't try to do some - // vkCreate* every BeginSwap, will reach this part again, so okay to set - // swap_swapchain_or_surface_recreation_needed_ back to true). - swap_swapchain_or_surface_recreation_needed_ = true; - util::DestroyAndNullHandle(dfn.vkDestroySwapchainKHR, device, - swap_swapchain_); - return false; - } - swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - swapchain_create_info.pNext = nullptr; - swapchain_create_info.flags = 0; - swapchain_create_info.surface = swap_surface_; - swapchain_create_info.minImageCount = kSwapchainMaxImageCount; - if (surface_capabilities.maxImageCount) { - swapchain_create_info.minImageCount = - std::min(swapchain_create_info.minImageCount, - surface_capabilities.maxImageCount); - } - swapchain_create_info.imageFormat = swap_surface_format_.format; - swapchain_create_info.imageColorSpace = swap_surface_format_.colorSpace; - swapchain_create_info.imageArrayLayers = 1; - swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - // FIXME(Triang3l): Allow a separate queue for present - see - // vulkan_provider.cc for details. - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapchain_create_info.queueFamilyIndexCount = 1; - swapchain_create_info.pQueueFamilyIndices = - &queue_family_graphics_compute; - // TODO(Triang3l): Support rotated transforms. - swapchain_create_info.preTransform = - VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - if (!(surface_capabilities.supportedCompositeAlpha & - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)) { - if (surface_capabilities.supportedCompositeAlpha & - VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) { - swapchain_create_info.compositeAlpha = - VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; - } else { - // Whatever. supportedCompositeAlpha must have at least one bit set, - // but if it somehow doesn't (impossible situation according to the - // specification, but who knows), just assume opaque. - uint32_t composite_alpha_bit_index; - if (xe::bit_scan_forward( - uint32_t(surface_capabilities.supportedCompositeAlpha), - &composite_alpha_bit_index)) { - swapchain_create_info.compositeAlpha = VkCompositeAlphaFlagBitsKHR( - uint32_t(1) << composite_alpha_bit_index); - } - } - } - swapchain_create_info.presentMode = swap_surface_present_mode_; - swapchain_create_info.clipped = VK_TRUE; - swapchain_create_info.oldSwapchain = swap_swapchain_; - VkResult swapchain_create_result = dfn.vkCreateSwapchainKHR( - device, &swapchain_create_info, nullptr, &swap_swapchain_); - // The old swapchain is retired even if vkCreateSwapchainKHR has failed. - if (swapchain_create_info.oldSwapchain != VK_NULL_HANDLE) { - dfn.vkDestroySwapchainKHR(device, swapchain_create_info.oldSwapchain, - nullptr); - } - if (swapchain_create_result != VK_SUCCESS) { - XELOGE("Failed to create a Vulkan swapchain"); - swap_swapchain_ = VK_NULL_HANDLE; - return false; - } - swap_swapchain_extent_ = swapchain_create_info.imageExtent; - - // The render pass is needed to create framebuffers for swapchain images. - // It depends on the surface format, and thus can be reused with different - // surfaces by different swapchains, so it has separate lifetime tracking. - // It's safe to fail now (though destroying the new swapchain), because - // the request to destroy the old VkSwapchain somehow (after retiring, or - // directly) has been fulfilled. - if (swap_render_pass_ == VK_NULL_HANDLE) { - VkAttachmentDescription render_pass_color_attachment; - render_pass_color_attachment.flags = 0; - render_pass_color_attachment.format = swap_surface_format_.format; - render_pass_color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - render_pass_color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - render_pass_color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - render_pass_color_attachment.stencilLoadOp = - VK_ATTACHMENT_LOAD_OP_DONT_CARE; - render_pass_color_attachment.stencilStoreOp = - VK_ATTACHMENT_STORE_OP_DONT_CARE; - render_pass_color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - render_pass_color_attachment.finalLayout = - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - VkAttachmentReference render_pass_color_attachment_reference; - render_pass_color_attachment_reference.attachment = 0; - render_pass_color_attachment_reference.layout = - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkSubpassDescription render_pass_subpass; - render_pass_subpass.flags = 0; - render_pass_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - render_pass_subpass.inputAttachmentCount = 0; - render_pass_subpass.pInputAttachments = nullptr; - render_pass_subpass.colorAttachmentCount = 1; - render_pass_subpass.pColorAttachments = - &render_pass_color_attachment_reference; - render_pass_subpass.pResolveAttachments = nullptr; - render_pass_subpass.pDepthStencilAttachment = nullptr; - render_pass_subpass.preserveAttachmentCount = 0; - render_pass_subpass.pPreserveAttachments = nullptr; - // Presentation engine does memory reading - external dependencies - // needed, and presentation doesn't occur in any normal pipeline stage, - // but it can be represented in the "bottom of pipeline" stage. - // https://software.intel.com/content/www/us/en/develop/articles/api-without-secrets-introduction-to-vulkan-part-4.html - VkSubpassDependency render_pass_dependencies[2]; - render_pass_dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - render_pass_dependencies[0].dstSubpass = 0; - render_pass_dependencies[0].srcStageMask = - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - render_pass_dependencies[0].dstStageMask = - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - render_pass_dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - // Using blending, so both reading and writing. - render_pass_dependencies[0].dstAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - render_pass_dependencies[0].dependencyFlags = - VK_DEPENDENCY_BY_REGION_BIT; - render_pass_dependencies[1].srcSubpass = 0; - render_pass_dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - render_pass_dependencies[1].srcStageMask = - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - render_pass_dependencies[1].dstStageMask = - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - render_pass_dependencies[1].srcAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - render_pass_dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - render_pass_dependencies[1].dependencyFlags = - VK_DEPENDENCY_BY_REGION_BIT; - VkRenderPassCreateInfo render_pass_create_info; - render_pass_create_info.sType = - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_create_info.pNext = nullptr; - render_pass_create_info.flags = 0; - render_pass_create_info.attachmentCount = 1; - render_pass_create_info.pAttachments = &render_pass_color_attachment; - render_pass_create_info.subpassCount = 1; - render_pass_create_info.pSubpasses = &render_pass_subpass; - render_pass_create_info.dependencyCount = - uint32_t(xe::countof(render_pass_dependencies)); - render_pass_create_info.pDependencies = render_pass_dependencies; - if (dfn.vkCreateRenderPass(device, &render_pass_create_info, nullptr, - &swap_render_pass_) != VK_SUCCESS) { - XELOGE("Failed to create the Vulkan presentation render pass."); - dfn.vkDestroySwapchainKHR(device, swap_swapchain_, nullptr); - swap_swapchain_ = VK_NULL_HANDLE; - return false; - } - } - - std::vector swapchain_images; - uint32_t swapchain_image_count; - VkResult swapchain_images_get_result; - for (;;) { - swapchain_image_count = uint32_t(swapchain_images.size()); - bool swapchain_images_was_empty = !swapchain_image_count; - swapchain_images_get_result = dfn.vkGetSwapchainImagesKHR( - device, swap_swapchain_, &swapchain_image_count, - swapchain_images_was_empty ? nullptr : swapchain_images.data()); - // If the original swapchain image count was 0 (first call), SUCCESS is - // returned, not INCOMPLETE. - if (swapchain_images_get_result == VK_SUCCESS || - swapchain_images_get_result == VK_INCOMPLETE) { - swapchain_images.resize(swapchain_image_count); - if (swapchain_images_get_result == VK_SUCCESS && - (!swapchain_images_was_empty || !swapchain_image_count)) { - break; - } - } else { - break; - } - } - if (swapchain_images_get_result != VK_SUCCESS || - swapchain_images.empty()) { - XELOGE("Failed to get Vulkan swapchain images"); - dfn.vkDestroySwapchainKHR(device, swap_swapchain_, nullptr); - swap_swapchain_ = VK_NULL_HANDLE; - return false; - } - assert_true(swap_swapchain_image_views_.empty()); - swap_swapchain_image_views_.reserve(swapchain_image_count); - assert_true(swap_swapchain_framebuffers_.empty()); - swap_swapchain_framebuffers_.reserve(swapchain_image_count); - VkImageViewCreateInfo swapchain_image_view_create_info; - swapchain_image_view_create_info.sType = - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - swapchain_image_view_create_info.pNext = nullptr; - swapchain_image_view_create_info.flags = 0; - swapchain_image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - swapchain_image_view_create_info.format = swap_surface_format_.format; - swapchain_image_view_create_info.components.r = - VK_COMPONENT_SWIZZLE_IDENTITY; - swapchain_image_view_create_info.components.g = - VK_COMPONENT_SWIZZLE_IDENTITY; - swapchain_image_view_create_info.components.b = - VK_COMPONENT_SWIZZLE_IDENTITY; - swapchain_image_view_create_info.components.a = - VK_COMPONENT_SWIZZLE_IDENTITY; - swapchain_image_view_create_info.subresourceRange.aspectMask = - VK_IMAGE_ASPECT_COLOR_BIT; - swapchain_image_view_create_info.subresourceRange.baseMipLevel = 0; - swapchain_image_view_create_info.subresourceRange.levelCount = 1; - swapchain_image_view_create_info.subresourceRange.baseArrayLayer = 0; - swapchain_image_view_create_info.subresourceRange.layerCount = 1; - VkFramebufferCreateInfo swapchain_framebuffer_create_info; - swapchain_framebuffer_create_info.sType = - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - swapchain_framebuffer_create_info.pNext = nullptr; - swapchain_framebuffer_create_info.flags = 0; - swapchain_framebuffer_create_info.renderPass = swap_render_pass_; - swapchain_framebuffer_create_info.attachmentCount = 1; - swapchain_framebuffer_create_info.width = swap_swapchain_extent_.width; - swapchain_framebuffer_create_info.height = swap_swapchain_extent_.height; - swapchain_framebuffer_create_info.layers = 1; - for (uint32_t i = 0; i < swapchain_image_count; ++i) { - VkImage swapchain_image = swapchain_images[i]; - swapchain_image_view_create_info.image = swapchain_image; - VkImageView swapchain_image_view; - if (dfn.vkCreateImageView(device, &swapchain_image_view_create_info, - nullptr, - &swapchain_image_view) != VK_SUCCESS) { - XELOGE("Failed to create Vulkan swapchain image views"); - DestroySwapchainFramebuffers(); - dfn.vkDestroySwapchainKHR(device, swap_swapchain_, nullptr); - swap_swapchain_ = VK_NULL_HANDLE; - return false; - } - swap_swapchain_image_views_.push_back(swapchain_image_view); - swapchain_framebuffer_create_info.pAttachments = &swapchain_image_view; - VkFramebuffer swapchain_framebuffer; - if (dfn.vkCreateFramebuffer(device, &swapchain_framebuffer_create_info, - nullptr, - &swapchain_framebuffer) != VK_SUCCESS) { - XELOGE("Failed to create Vulkan swapchain framebuffers"); - DestroySwapchainFramebuffers(); - dfn.vkDestroySwapchainKHR(device, swap_swapchain_, nullptr); - swap_swapchain_ = VK_NULL_HANDLE; - return false; - } - swap_swapchain_framebuffers_.push_back(swapchain_framebuffer); - } - } - - if (swap_swapchain_ == VK_NULL_HANDLE) { - return false; - } - assert_true(swap_surface_ != VK_NULL_HANDLE); - assert_true(swap_render_pass_ != VK_NULL_HANDLE); - assert_false(swap_swapchain_image_views_.empty()); - assert_false(swap_swapchain_framebuffers_.empty()); - - // Await the frame data to be available before doing anything else. - if (swap_submission_completed_ + kSwapchainMaxImageCount < - swap_submission_current_) { - if (!AwaitSwapSubmissionsCompletion( - swap_submission_current_ - kSwapchainMaxImageCount, false)) { - XELOGE("Failed to await the Vulkan presentation submission fences"); - return false; - } - } - - const SwapSubmission& submission = - swap_submissions_[swap_submission_current_ % kSwapchainMaxImageCount]; - if (dfn.vkResetCommandPool(device, submission.command_pool, 0) != - VK_SUCCESS) { - XELOGE("Failed to reset the Vulkan presentation command pool"); - return false; - } - - // After the image is acquired, this function must not fail before the - // semaphore has been signaled, and the image also must be returned to the - // swapchain. - uint32_t acquired_image_index; - switch (dfn.vkAcquireNextImageKHR(device, swap_swapchain_, UINT64_MAX, - submission.image_acquisition_semaphore, - nullptr, &acquired_image_index)) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - // Not recreating in case of suboptimal, just to prevent a recreation - // loop in case the newly created swapchain is suboptimal too. - break; - case VK_ERROR_DEVICE_LOST: - context_lost_ = true; - return false; - case VK_ERROR_OUT_OF_DATE_KHR: - case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: - swap_swapchain_or_surface_recreation_needed_ = true; - continue; - case VK_ERROR_SURFACE_LOST_KHR: - RequestSurfaceRecreation(); - continue; - default: - return false; - } - swap_swapchain_image_current_ = acquired_image_index; - - VkCommandBufferBeginInfo command_buffer_begin_info; - command_buffer_begin_info.sType = - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - command_buffer_begin_info.pNext = nullptr; - command_buffer_begin_info.flags = - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - command_buffer_begin_info.pInheritanceInfo = nullptr; - dfn.vkBeginCommandBuffer(submission.command_buffer, - &command_buffer_begin_info); - VkClearValue clear_value; - GetClearColor(clear_value.color.float32); - VkRenderPassBeginInfo render_pass_begin_info; - render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_begin_info.pNext = nullptr; - render_pass_begin_info.renderPass = swap_render_pass_; - render_pass_begin_info.framebuffer = - swap_swapchain_framebuffers_[acquired_image_index]; - render_pass_begin_info.renderArea.offset.x = 0; - render_pass_begin_info.renderArea.offset.y = 0; - render_pass_begin_info.renderArea.extent = swap_swapchain_extent_; - render_pass_begin_info.clearValueCount = 1; - render_pass_begin_info.pClearValues = &clear_value; - dfn.vkCmdBeginRenderPass(submission.command_buffer, &render_pass_begin_info, - VK_SUBPASS_CONTENTS_INLINE); - - return true; - } - - // vkAcquireNextImageKHR returned VK_ERROR_OUT_OF_DATE_KHR even after - // recreation. - return false; -} - -void VulkanContext::EndSwap() { - if (!target_window_ || context_lost_) { - return; - } - assert_true(swap_swapchain_image_current_ != UINT32_MAX); - if (swap_swapchain_image_current_ == UINT32_MAX) { - return; - } - - VulkanProvider& provider = GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - - const SwapSubmission& submission = - swap_submissions_[swap_submission_current_ % kSwapchainMaxImageCount]; - VkCommandBuffer submit_command_buffers[2]; - uint32_t submit_command_buffer_count = 0; - if (submission.setup_command_buffer_index != UINT32_MAX) { - VkCommandBuffer submit_setup_command_buffer = - swap_setup_command_buffers_[submission.setup_command_buffer_index] - .second; - dfn.vkEndCommandBuffer(submit_setup_command_buffer); - submit_command_buffers[submit_command_buffer_count++] = - submit_setup_command_buffer; - } - dfn.vkCmdEndRenderPass(submission.command_buffer); - dfn.vkEndCommandBuffer(submission.command_buffer); - submit_command_buffers[submit_command_buffer_count++] = - submission.command_buffer; - dfn.vkResetFences(device, 1, &submission.fence); - VkSubmitInfo submit_info; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = nullptr; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &submission.image_acquisition_semaphore; - VkPipelineStageFlags image_acquisition_semaphore_wait_stage = - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - submit_info.pWaitDstStageMask = &image_acquisition_semaphore_wait_stage; - submit_info.commandBufferCount = submit_command_buffer_count; - submit_info.pCommandBuffers = submit_command_buffers; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &submission.render_completion_semaphore; - VkResult submit_result = - provider.SubmitToGraphicsComputeQueue(1, &submit_info, submission.fence); - if (submit_result != VK_SUCCESS) { - // If failed, can't even return the swapchain image - so treat all errors as - // context loss. - context_lost_ = true; - return; - } - ++swap_submission_current_; - - VkPresentInfoKHR present_info; - present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - present_info.pNext = nullptr; - present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = &submission.render_completion_semaphore; - present_info.swapchainCount = 1; - present_info.pSwapchains = &swap_swapchain_; - present_info.pImageIndices = &swap_swapchain_image_current_; - present_info.pResults = nullptr; - VkResult present_result = provider.Present(&present_info); - swap_swapchain_image_current_ = UINT32_MAX; - switch (present_result) { - case VK_SUCCESS: - case VK_SUBOPTIMAL_KHR: - // Not recreating in case of suboptimal, just to prevent a recreation - // loop in case the newly created swapchain is suboptimal too. - break; - case VK_ERROR_OUT_OF_DATE_KHR: - case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: - swap_swapchain_or_surface_recreation_needed_ = true; - return; - case VK_ERROR_SURFACE_LOST_KHR: - // Safe to await submission completion now - swap_submission_current_ has - // already been incremented to the next frame. - RequestSurfaceRecreation(); - return; - default: - // Treat any error as device loss since it would leave the semaphore - // forever signaled anyway, and the image won't be returned to the - // swapchain. - context_lost_ = true; - return; - } -} - -std::unique_ptr VulkanContext::Capture() { - // TODO(Triang3l): Read back swap chain front buffer. - return nullptr; -} - -void VulkanContext::RequestSurfaceRecreation() { -#if XE_PLATFORM_ANDROID - // The surface doesn't exist when the activity is in background. - swap_swapchain_or_surface_recreation_needed_ = - target_window_->native_handle() != nullptr; -#else - swap_swapchain_or_surface_recreation_needed_ = true; -#endif - if (swap_surface_ == VK_NULL_HANDLE) { - return; - } - AwaitAllSwapSubmissionsCompletion(); - DestroySwapchainFramebuffers(); - const VulkanProvider& provider = GetVulkanProvider(); - const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); - VkInstance instance = provider.instance(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - util::DestroyAndNullHandle(dfn.vkDestroySwapchainKHR, device, - swap_swapchain_); - ifn.vkDestroySurfaceKHR(instance, swap_surface_, nullptr); - swap_surface_ = VK_NULL_HANDLE; -} - -bool VulkanContext::AwaitSwapSubmissionsCompletion(uint64_t awaited_submission, - bool ignore_result) { - assert_not_null(target_window_); - assert_true(awaited_submission < swap_submission_current_); - const VulkanProvider& provider = GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - VkFence fences[kSwapchainMaxImageCount]; - uint32_t fence_count = 0; - while (swap_submission_completed_ + 1 + fence_count <= awaited_submission) { - assert_true(fence_count < kSwapchainMaxImageCount); - uint32_t submission_index = (swap_submission_completed_ + 1 + fence_count) % - kSwapchainMaxImageCount; - fences[fence_count++] = swap_submissions_[submission_index].fence; - } - if (!fence_count) { - return true; - } - VkResult result = - dfn.vkWaitForFences(device, fence_count, fences, VK_TRUE, UINT64_MAX); - if (!ignore_result && result != VK_SUCCESS) { - return false; - } - // Reclaim setup command buffers if used. - for (uint32_t i = 0; i < fence_count; ++i) { - uint32_t submission_index = - (swap_submission_completed_ + 1 + i) % kSwapchainMaxImageCount; - uint32_t& setup_command_buffer_index = - swap_submissions_[submission_index].setup_command_buffer_index; - if (setup_command_buffer_index == UINT32_MAX) { - continue; - } - assert_zero(swap_setup_command_buffers_free_bits_ & - (uint32_t(1) << setup_command_buffer_index)); - swap_setup_command_buffers_free_bits_ |= uint32_t(1) - << setup_command_buffer_index; - setup_command_buffer_index = UINT32_MAX; - } - swap_submission_completed_ += fence_count; - return result == VK_SUCCESS; -} - -VkCommandBuffer VulkanContext::AcquireSwapSetupCommandBuffer() { - assert_not_null(target_window_); - - uint32_t& submission_command_buffer_index = - swap_submissions_[swap_submission_current_ % kSwapchainMaxImageCount] - .setup_command_buffer_index; - if (submission_command_buffer_index != UINT32_MAX) { - // A command buffer is already being recorded. - return swap_setup_command_buffers_[submission_command_buffer_index].second; - } - - const VulkanProvider& provider = GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - - VkCommandBufferBeginInfo command_buffer_begin_info; - command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - command_buffer_begin_info.pNext = nullptr; - command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - command_buffer_begin_info.pInheritanceInfo = nullptr; - - // Try to use a recycled one. - uint32_t command_buffer_index; - if (xe::bit_scan_forward(swap_setup_command_buffers_free_bits_, - &command_buffer_index)) { - const std::pair& command_buffer = - swap_setup_command_buffers_[command_buffer_index]; - if (dfn.vkResetCommandPool(device, command_buffer.first, 0) != VK_SUCCESS || - dfn.vkBeginCommandBuffer(command_buffer.second, - &command_buffer_begin_info) != VK_SUCCESS) { - return VK_NULL_HANDLE; - } - submission_command_buffer_index = command_buffer_index; - swap_setup_command_buffers_free_bits_ &= - ~(uint32_t(1) << command_buffer_index); - return command_buffer.second; - } - - // Create a new command buffer. - assert_true(swap_setup_command_buffers_allocated_count_ < - kSwapchainMaxImageCount); - if (swap_setup_command_buffers_allocated_count_ >= kSwapchainMaxImageCount) { - return VK_NULL_HANDLE; - } - VkCommandPoolCreateInfo command_pool_create_info; - command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - command_pool_create_info.pNext = nullptr; - command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; - command_pool_create_info.queueFamilyIndex = - provider.queue_family_graphics_compute(); - VkCommandPool new_command_pool; - if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr, - &new_command_pool) != VK_SUCCESS) { - return VK_NULL_HANDLE; - } - VkCommandBufferAllocateInfo command_buffer_allocate_info; - command_buffer_allocate_info.sType = - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.pNext = nullptr; - command_buffer_allocate_info.commandPool = new_command_pool; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - command_buffer_allocate_info.commandBufferCount = 1; - VkCommandBuffer new_command_buffer; - if (dfn.vkAllocateCommandBuffers(device, &command_buffer_allocate_info, - &new_command_buffer) != VK_SUCCESS || - dfn.vkBeginCommandBuffer(new_command_buffer, - &command_buffer_begin_info) != VK_SUCCESS) { - dfn.vkDestroyCommandPool(device, new_command_pool, nullptr); - return VK_NULL_HANDLE; - } - uint32_t new_command_buffer_index = - swap_setup_command_buffers_allocated_count_++; - submission_command_buffer_index = new_command_buffer_index; - swap_setup_command_buffers_[new_command_buffer_index] = - std::make_pair(new_command_pool, new_command_buffer); - return new_command_buffer; -} - -void VulkanContext::DestroySwapchainFramebuffers() { - assert_not_null(target_window_); - const VulkanProvider& provider = GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - for (VkFramebuffer framebuffer : swap_swapchain_framebuffers_) { - dfn.vkDestroyFramebuffer(device, framebuffer, nullptr); - } - swap_swapchain_framebuffers_.clear(); - for (VkImageView image_view : swap_swapchain_image_views_) { - dfn.vkDestroyImageView(device, image_view, nullptr); - } - swap_swapchain_image_views_.clear(); -} - -} // namespace vulkan -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_context.h b/src/xenia/ui/vulkan/vulkan_context.h deleted file mode 100644 index 00289c19b..000000000 --- a/src/xenia/ui/vulkan/vulkan_context.h +++ /dev/null @@ -1,145 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_VULKAN_CONTEXT_H_ -#define XENIA_UI_VULKAN_VULKAN_CONTEXT_H_ - -#include -#include -#include -#include - -#include "xenia/ui/graphics_context.h" -#include "xenia/ui/vulkan/vulkan_immediate_drawer.h" -#include "xenia/ui/vulkan/vulkan_provider.h" - -#define FINE_GRAINED_DRAW_SCOPES 1 - -namespace xe { -namespace ui { -namespace vulkan { - -class VulkanContext : public GraphicsContext { - public: - ~VulkanContext() override; - - ImmediateDrawer* immediate_drawer() override; - - bool WasLost() override; - - bool BeginSwap() override; - void EndSwap() override; - - std::unique_ptr Capture() override; - - VulkanProvider& GetVulkanProvider() const { - return static_cast(*provider_); - } - - void RequestSurfaceRecreation(); - - VkCommandBuffer GetSwapCommandBuffer() const { - return swap_submissions_[swap_submission_current_ % kSwapchainMaxImageCount] - .command_buffer; - } - VkCommandBuffer AcquireSwapSetupCommandBuffer(); - uint64_t swap_submission_current() const { return swap_submission_current_; } - uint64_t swap_submission_completed() const { - return swap_submission_completed_; - } - - const VkSurfaceFormatKHR& swap_surface_format() const { - return swap_surface_format_; - } - VkRenderPass swap_render_pass() const { return swap_render_pass_; } - - private: - friend class VulkanProvider; - explicit VulkanContext(VulkanProvider* provider, Window* target_window); - bool Initialize(); - - private: - void Shutdown(); - - bool AwaitSwapSubmissionsCompletion(uint64_t awaited_submission, - bool ignore_result); - void AwaitAllSwapSubmissionsCompletion() { - // Current starts from 1, so subtracting 1 can't result in a negative value. - AwaitSwapSubmissionsCompletion(swap_submission_current_ - 1, true); - } - - // AwaitAllSwapSubmissionsCompletion must be called before. As this can be - // used in swapchain creation or in shutdown, - // swap_swapchain_or_surface_recreation_needed_ won't be set by this. - void DestroySwapchainFramebuffers(); - - bool context_lost_ = false; - - // Actual image count may be less, depending on what the surface can provide. - static constexpr uint32_t kSwapchainMaxImageCount = 3; - - // Because of the nature of Vulkan fences (that they belong only to their - // specific submission, not the submission and all prior submissions), ALL - // fences since the last completed submission to the needed submission should - // individually be checked, not just the last one. However, this submission - // number abstraction hides the loosely ordered design of Vulkan submissions - // (it's okay to wait first for completion of A, then of B, no matter if they - // are actually completed in AB or in BA order). - - // May be used infrequently, so allocated on demand (to only keep 1 rather - // than 3). - std::pair - swap_setup_command_buffers_[kSwapchainMaxImageCount]; - uint32_t swap_setup_command_buffers_allocated_count_ = 0; - uint32_t swap_setup_command_buffers_free_bits_ = 0; - - struct SwapSubmission { - // One pool per frame, with resetting the pool itself rather than individual - // command buffers (resetting command buffers themselves is not recommended - // by Arm since it makes the pool unable to use a single big allocation), as - // recommended by Nvidia (Direct3D 12-like way): - // https://developer.nvidia.com/sites/default/files/akamai/gameworks/blog/munich/mschott_vulkan_multi_threading.pdf - VkFence fence = VK_NULL_HANDLE; - // One pair of semaphores per frame because queue operations may be done out - // of order. - VkSemaphore image_acquisition_semaphore = VK_NULL_HANDLE; - VkSemaphore render_completion_semaphore = VK_NULL_HANDLE; - VkCommandPool command_pool = VK_NULL_HANDLE; - VkCommandBuffer command_buffer; - uint32_t setup_command_buffer_index = UINT32_MAX; - }; - SwapSubmission swap_submissions_[kSwapchainMaxImageCount]; - uint64_t swap_submission_current_ = 1; - uint64_t swap_submission_completed_ = 0; - - VkSurfaceKHR swap_surface_ = VK_NULL_HANDLE; - VkSurfaceFormatKHR swap_surface_format_ = {VK_FORMAT_UNDEFINED, - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; - VkPresentModeKHR swap_surface_present_mode_; - VkRenderPass swap_render_pass_ = VK_NULL_HANDLE; - VkSwapchainKHR swap_swapchain_ = VK_NULL_HANDLE; - VkExtent2D swap_swapchain_extent_; - std::vector swap_swapchain_image_views_; - std::vector swap_swapchain_framebuffers_; - - uint32_t swap_swapchain_image_current_ = UINT32_MAX; - - // Attempts to recreate the swapchain will only be made in BeginSwap if this - // is true (set when something relevant is changed), so if creation fails, - // there won't be attempts every frame again and again. - bool swap_swapchain_or_surface_recreation_needed_ = false; - - std::unique_ptr immediate_drawer_ = nullptr; -}; - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_VULKAN_CONTEXT_H_ diff --git a/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc b/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc index 245fbb684..7d2753a28 100644 --- a/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc +++ b/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc @@ -17,14 +17,14 @@ #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" -#include "xenia/ui/vulkan/vulkan_context.h" +#include "xenia/ui/vulkan/vulkan_presenter.h" #include "xenia/ui/vulkan/vulkan_util.h" namespace xe { namespace ui { namespace vulkan { -// Generated with `xb genspirv`. +// Generated with `xb buildshaders`. #include "xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.h" #include "xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h" @@ -34,15 +34,61 @@ VulkanImmediateDrawer::VulkanImmediateTexture::~VulkanImmediateTexture() { } } -VulkanImmediateDrawer::VulkanImmediateDrawer(VulkanContext& graphics_context) - : ImmediateDrawer(&graphics_context), context_(graphics_context) {} +VulkanImmediateDrawer::~VulkanImmediateDrawer() { + // Await GPU usage completion of all draws and texture uploads (which happen + // before draws). + auto vulkan_presenter = static_cast(presenter()); + if (vulkan_presenter) { + vulkan_presenter->AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + } -VulkanImmediateDrawer::~VulkanImmediateDrawer() { Shutdown(); } + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_line_); + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_triangle_); + + util::DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, device, + pipeline_layout_); + + for (auto& deleted_texture : textures_deleted_) { + DestroyTextureResource(deleted_texture.first); + } + for (SubmittedTextureUploadBuffer& submitted_texture_upload_buffer : + texture_upload_buffers_submitted_) { + dfn.vkDestroyBuffer(device, submitted_texture_upload_buffer.buffer, + nullptr); + dfn.vkFreeMemory(device, submitted_texture_upload_buffer.buffer_memory, + nullptr); + } + for (PendingTextureUpload& pending_texture_upload : + texture_uploads_pending_) { + dfn.vkDestroyBuffer(device, pending_texture_upload.buffer, nullptr); + dfn.vkFreeMemory(device, pending_texture_upload.buffer_memory, nullptr); + } + for (VulkanImmediateTexture* texture : textures_) { + if (texture->immediate_drawer_ != this) { + continue; + } + texture->immediate_drawer_ = nullptr; + DestroyTextureResource(texture->resource_); + } + if (white_texture_.image != VK_NULL_HANDLE) { + DestroyTextureResource(white_texture_); + } + + for (TextureDescriptorPool* pool : texture_descriptor_pools_) { + dfn.vkDestroyDescriptorPool(device, pool->pool, nullptr); + delete pool; + } + util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, device, + texture_descriptor_set_layout_); +} bool VulkanImmediateDrawer::Initialize() { - const VulkanProvider& provider = context_.GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkDescriptorSetLayoutBinding texture_descriptor_set_layout_binding; texture_descriptor_set_layout_binding.binding = 0; @@ -64,9 +110,8 @@ bool VulkanImmediateDrawer::Initialize() { device, &texture_descriptor_set_layout_create_info, nullptr, &texture_descriptor_set_layout_) != VK_SUCCESS) { XELOGE( - "Failed to create the immediate drawer Vulkan combined image sampler " + "VulkanImmediateDrawer: Failed to create the combined image sampler " "descriptor set layout"); - Shutdown(); return false; } @@ -76,11 +121,14 @@ bool VulkanImmediateDrawer::Initialize() { if (!CreateTextureResource(1, 1, ImmediateTextureFilter::kNearest, false, nullptr, white_texture_, white_texture_pending_upload_index)) { - XELOGE("Failed to create a blank texture for the Vulkan immediate drawer"); - Shutdown(); + XELOGE("VulkanImmediateDrawer: Failed to create a blank texture"); return false; } + vertex_buffer_pool_ = std::make_unique( + provider_, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + VkPushConstantRange push_constant_ranges[1]; push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; push_constant_ranges[0].offset = offsetof(PushConstants, vertex); @@ -97,77 +145,16 @@ bool VulkanImmediateDrawer::Initialize() { pipeline_layout_create_info.pPushConstantRanges = push_constant_ranges; if (dfn.vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &pipeline_layout_) != VK_SUCCESS) { - XELOGE("Failed to create the immediate drawer Vulkan pipeline layout"); - Shutdown(); + XELOGE("VulkanImmediateDrawer: Failed to create the pipeline layout"); return false; } - vertex_buffer_pool_ = std::make_unique( - provider, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - // Reset the current state. - current_command_buffer_ = VK_NULL_HANDLE; batch_open_ = false; return true; } -void VulkanImmediateDrawer::Shutdown() { - const VulkanProvider& provider = context_.GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); - - util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_line_); - util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_triangle_); - - vertex_buffer_pool_.reset(); - - util::DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, device, - pipeline_layout_); - - for (auto& deleted_texture : textures_deleted_) { - DestroyTextureResource(deleted_texture.first); - } - textures_deleted_.clear(); - for (SubmittedTextureUploadBuffer& submitted_texture_upload_buffer : - texture_upload_buffers_submitted_) { - dfn.vkDestroyBuffer(device, submitted_texture_upload_buffer.buffer, - nullptr); - dfn.vkFreeMemory(device, submitted_texture_upload_buffer.buffer_memory, - nullptr); - } - texture_upload_buffers_submitted_.clear(); - for (PendingTextureUpload& pending_texture_upload : - texture_uploads_pending_) { - dfn.vkDestroyBuffer(device, pending_texture_upload.buffer, nullptr); - dfn.vkFreeMemory(device, pending_texture_upload.buffer_memory, nullptr); - } - texture_uploads_pending_.clear(); - for (VulkanImmediateTexture* texture : textures_) { - if (texture->immediate_drawer_ != this) { - continue; - } - texture->immediate_drawer_ = nullptr; - DestroyTextureResource(texture->resource_); - } - textures_.clear(); - if (white_texture_.image != VK_NULL_HANDLE) { - DestroyTextureResource(white_texture_); - white_texture_.image = VK_NULL_HANDLE; - } - - texture_descriptor_pool_recycled_first_ = nullptr; - texture_descriptor_pool_unallocated_first_ = nullptr; - for (TextureDescriptorPool* pool : texture_descriptor_pools_) { - dfn.vkDestroyDescriptorPool(device, pool->pool, nullptr); - delete pool; - } - texture_descriptor_pools_.clear(); - util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, device, - texture_descriptor_set_layout_); -} - std::unique_ptr VulkanImmediateDrawer::CreateTexture( uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool is_repeated, const uint8_t* data) { @@ -187,26 +174,30 @@ std::unique_ptr VulkanImmediateDrawer::CreateTexture( return std::move(texture); } -void VulkanImmediateDrawer::Begin(int render_target_width, - int render_target_height) { - assert_true(current_command_buffer_ == VK_NULL_HANDLE); +void VulkanImmediateDrawer::Begin(UIDrawContext& ui_draw_context, + float coordinate_space_width, + float coordinate_space_height) { + ImmediateDrawer::Begin(ui_draw_context, coordinate_space_width, + coordinate_space_height); + assert_false(batch_open_); - if (!EnsurePipelinesCreated()) { - return; - } + const VulkanUIDrawContext& vulkan_ui_draw_context = + static_cast(ui_draw_context); - current_command_buffer_ = context_.GetSwapCommandBuffer(); + // Update the submission index to be used throughout the current immediate + // drawer paint. + last_paint_submission_index_ = + vulkan_ui_draw_context.submission_index_current(); + last_completed_submission_index_ = + vulkan_ui_draw_context.submission_index_completed(); - uint64_t submission_completed = context_.swap_submission_completed(); - - const VulkanProvider& provider = context_.GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Destroy deleted textures. for (auto it = textures_deleted_.begin(); it != textures_deleted_.end();) { - if (it->second > submission_completed) { + if (it->second > last_completed_submission_index_) { ++it; continue; } @@ -220,7 +211,8 @@ void VulkanImmediateDrawer::Begin(int render_target_width, // Release upload buffers for completed texture uploads. auto erase_texture_uploads_end = texture_upload_buffers_submitted_.begin(); while (erase_texture_uploads_end != texture_upload_buffers_submitted_.end()) { - if (erase_texture_uploads_end->submission_index > submission_completed) { + if (erase_texture_uploads_end->submission_index > + last_completed_submission_index_) { break; } dfn.vkDestroyBuffer(device, erase_texture_uploads_end->buffer, nullptr); @@ -230,22 +222,34 @@ void VulkanImmediateDrawer::Begin(int render_target_width, texture_upload_buffers_submitted_.erase( texture_upload_buffers_submitted_.begin(), erase_texture_uploads_end); - vertex_buffer_pool_->Reclaim(submission_completed); + vertex_buffer_pool_->Reclaim(last_completed_submission_index_); + + // Begin drawing. + + // Update the framebuffer attachment format in the pipelines - may await + // submission completion if changing. + if (!EnsurePipelinesCreatedForCurrentRenderPass()) { + // Failed to create the pipelines - don't draw anything. + return; + } + + VkCommandBuffer draw_command_buffer = + vulkan_ui_draw_context.draw_command_buffer(); - current_render_target_extent_.width = uint32_t(render_target_width); - current_render_target_extent_.height = uint32_t(render_target_height); VkViewport viewport; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = float(render_target_width); - viewport.height = float(render_target_height); + viewport.width = float(vulkan_ui_draw_context.render_target_width()); + viewport.height = float(vulkan_ui_draw_context.render_target_height()); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; - dfn.vkCmdSetViewport(current_command_buffer_, 0, 1, &viewport); + dfn.vkCmdSetViewport(draw_command_buffer, 0, 1, &viewport); PushConstants::Vertex push_constants_vertex; - push_constants_vertex.viewport_size_inv[0] = 1.0f / viewport.width; - push_constants_vertex.viewport_size_inv[1] = 1.0f / viewport.height; - dfn.vkCmdPushConstants(current_command_buffer_, pipeline_layout_, + push_constants_vertex.coordinate_space_size_inv[0] = + 1.0f / coordinate_space_width; + push_constants_vertex.coordinate_space_size_inv[1] = + 1.0f / coordinate_space_height; + dfn.vkCmdPushConstants(draw_command_buffer, pipeline_layout_, VK_SHADER_STAGE_VERTEX_BIT, offsetof(PushConstants, vertex), sizeof(PushConstants::Vertex), &push_constants_vertex); @@ -260,29 +264,28 @@ void VulkanImmediateDrawer::Begin(int render_target_width, void VulkanImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { assert_false(batch_open_); - if (current_command_buffer_ == VK_NULL_HANDLE) { - // No surface, or failed to create the pipelines. - return; - } - uint64_t submission_current = context_.swap_submission_current(); - const VulkanProvider::DeviceFunctions& dfn = - context_.GetVulkanProvider().dfn(); + const VulkanUIDrawContext& vulkan_ui_draw_context = + *static_cast(ui_draw_context()); + VkCommandBuffer draw_command_buffer = + vulkan_ui_draw_context.draw_command_buffer(); + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); // Bind the vertices. size_t vertex_buffer_size = sizeof(ImmediateVertex) * batch.vertex_count; VkBuffer vertex_buffer; VkDeviceSize vertex_buffer_offset; void* vertex_buffer_mapping = vertex_buffer_pool_->Request( - submission_current, vertex_buffer_size, sizeof(float), vertex_buffer, - vertex_buffer_offset); + last_paint_submission_index_, vertex_buffer_size, sizeof(float), + vertex_buffer, vertex_buffer_offset); if (!vertex_buffer_mapping) { - XELOGE("Failed to get a buffer for {} vertices in the immediate drawer", + XELOGE("VulkanImmediateDrawer: Failed to get a buffer for {} vertices", batch.vertex_count); return; } std::memcpy(vertex_buffer_mapping, batch.vertices, vertex_buffer_size); - dfn.vkCmdBindVertexBuffers(current_command_buffer_, 0, 1, &vertex_buffer, + dfn.vkCmdBindVertexBuffers(draw_command_buffer, 0, 1, &vertex_buffer, &vertex_buffer_offset); // Bind the indices. @@ -292,15 +295,15 @@ void VulkanImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { VkBuffer index_buffer; VkDeviceSize index_buffer_offset; void* index_buffer_mapping = vertex_buffer_pool_->Request( - submission_current, index_buffer_size, sizeof(uint16_t), index_buffer, - index_buffer_offset); + last_paint_submission_index_, index_buffer_size, sizeof(uint16_t), + index_buffer, index_buffer_offset); if (!index_buffer_mapping) { - XELOGE("Failed to get a buffer for {} indices in the immediate drawer", + XELOGE("VulkanImmediateDrawer: Failed to get a buffer for {} indices", batch.index_count); return; } std::memcpy(index_buffer_mapping, batch.indices, index_buffer_size); - dfn.vkCmdBindIndexBuffer(current_command_buffer_, index_buffer, + dfn.vkCmdBindIndexBuffer(draw_command_buffer, index_buffer, index_buffer_offset, VK_INDEX_TYPE_UINT16); } @@ -309,40 +312,18 @@ void VulkanImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) { if (!batch_open_) { - // No surface, or failed to create the pipelines, or could be an error while - // obtaining the vertex and index buffers. + // Could have been an error while obtaining the vertex and index buffers, + // for instance. return; } - const VulkanProvider::DeviceFunctions& dfn = - context_.GetVulkanProvider().dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + const VulkanUIDrawContext& vulkan_ui_draw_context = + *static_cast(ui_draw_context()); + VkCommandBuffer draw_command_buffer = + vulkan_ui_draw_context.draw_command_buffer(); - // Set the scissor rectangle if enabled. - VkRect2D scissor; - if (draw.scissor) { - scissor.offset.x = draw.scissor_rect[0]; - scissor.offset.y = current_render_target_extent_.height - - (draw.scissor_rect[1] + draw.scissor_rect[3]); - scissor.extent.width = std::max(draw.scissor_rect[2], 0); - scissor.extent.height = std::max(draw.scissor_rect[3], 0); - } else { - scissor.offset.x = 0; - scissor.offset.y = 0; - scissor.extent = current_render_target_extent_; - } - if (!scissor.extent.width || !scissor.extent.height) { - // Nothing is visible (used as the default current_scissor_ value also). - return; - } - if (current_scissor_.offset.x != scissor.offset.x || - current_scissor_.offset.y != scissor.offset.y || - current_scissor_.extent.width != scissor.extent.width || - current_scissor_.extent.height != scissor.extent.height) { - current_scissor_ = scissor; - dfn.vkCmdSetScissor(current_command_buffer_, 0, 1, &scissor); - } - - // Bind the pipeline for the current primitive type. + // Get the pipeline for the current primitive type. VkPipeline pipeline; switch (draw.primitive_type) { case ImmediatePrimitiveType::kLines: @@ -355,10 +336,35 @@ void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) { assert_unhandled_case(draw.primitive_type); return; } + if (pipeline == VK_NULL_HANDLE) { + // Failed to create the pipeline. + return; + } + + // Set the scissor rectangle if enabled. + VkRect2D scissor; + uint32_t scissor_left, scissor_top; + if (!ScissorToRenderTarget(draw, scissor_left, scissor_top, + scissor.extent.width, scissor.extent.height)) { + // Nothing is visible (zero area is used as the default current_scissor_ + // value also). + return; + } + scissor.offset.x = int32_t(scissor_left); + scissor.offset.y = int32_t(scissor_top); + if (current_scissor_.offset.x != scissor.offset.x || + current_scissor_.offset.y != scissor.offset.y || + current_scissor_.extent.width != scissor.extent.width || + current_scissor_.extent.height != scissor.extent.height) { + current_scissor_ = scissor; + dfn.vkCmdSetScissor(draw_command_buffer, 0, 1, &scissor); + } + + // Bind the pipeline for the primitive type if the scissor is not empty. if (current_pipeline_ != pipeline) { current_pipeline_ = pipeline; - dfn.vkCmdBindPipeline(current_command_buffer_, - VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + dfn.vkCmdBindPipeline(draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeline); } // Bind the texture. @@ -367,7 +373,7 @@ void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) { static_cast(draw.texture); if (texture && texture->immediate_drawer_ == this) { texture_descriptor_index = texture->resource_.descriptor_index; - texture->last_usage_submission_ = context_.swap_submission_current(); + texture->last_usage_submission_ = last_paint_submission_index_; } else { texture_descriptor_index = white_texture_.descriptor_index; } @@ -376,16 +382,16 @@ void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) { VkDescriptorSet texture_descriptor_set = GetTextureDescriptor(texture_descriptor_index); dfn.vkCmdBindDescriptorSets( - current_command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline_layout_, 0, 1, &texture_descriptor_set, 0, nullptr); + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, + 0, 1, &texture_descriptor_set, 0, nullptr); } // Draw. if (batch_has_index_buffer_) { - dfn.vkCmdDrawIndexed(current_command_buffer_, draw.count, 1, - draw.index_offset, draw.base_vertex, 0); + dfn.vkCmdDrawIndexed(draw_command_buffer, draw.count, 1, draw.index_offset, + draw.base_vertex, 0); } else { - dfn.vkCmdDraw(current_command_buffer_, draw.count, 1, draw.base_vertex, 0); + dfn.vkCmdDraw(draw_command_buffer, draw.count, 1, draw.base_vertex, 0); } } @@ -393,21 +399,18 @@ void VulkanImmediateDrawer::EndDrawBatch() { batch_open_ = false; } void VulkanImmediateDrawer::End() { assert_false(batch_open_); - if (current_command_buffer_ == VK_NULL_HANDLE) { - // Didn't draw anything because the of some issue or surface not being - // available. - return; - } - // Copy textures. + // Upload textures. if (!texture_uploads_pending_.empty()) { + VulkanPresenter& vulkan_presenter = + *static_cast(presenter()); VkCommandBuffer setup_command_buffer = - context_.AcquireSwapSetupCommandBuffer(); + vulkan_presenter.AcquireUISetupCommandBufferFromUIThread(); if (setup_command_buffer != VK_NULL_HANDLE) { - const VulkanProvider::DeviceFunctions& dfn = - context_.GetVulkanProvider().dfn(); size_t texture_uploads_pending_count = texture_uploads_pending_.size(); - uint64_t submission_current = context_.swap_submission_current(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + const VulkanUIDrawContext& vulkan_ui_draw_context = + *static_cast(ui_draw_context()); // Transition to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. std::vector image_memory_barriers; @@ -464,9 +467,10 @@ void VulkanImmediateDrawer::End() { pending_texture_upload.buffer; submitted_texture_upload_buffer.buffer_memory = pending_texture_upload.buffer_memory; - submitted_texture_upload_buffer.submission_index = submission_current; + submitted_texture_upload_buffer.submission_index = + last_paint_submission_index_; } else { - // Clearing (initializing the empty image). + // Clearing (initializing the special empty image). VkClearColorValue white_clear_value; white_clear_value.float32[0] = 1.0f; white_clear_value.float32[1] = 1.0f; @@ -490,7 +494,7 @@ void VulkanImmediateDrawer::End() { if (pending_texture_upload.texture) { pending_texture_upload.texture->last_usage_submission_ = - submission_current; + last_paint_submission_index_; pending_texture_upload.texture->pending_upload_index_ = SIZE_MAX; } } @@ -504,54 +508,90 @@ void VulkanImmediateDrawer::End() { } vertex_buffer_pool_->FlushWrites(); - current_command_buffer_ = VK_NULL_HANDLE; + + ImmediateDrawer::End(); } -bool VulkanImmediateDrawer::EnsurePipelinesCreated() { - VkFormat swap_surface_format = context_.swap_surface_format().format; - if (swap_surface_format == pipeline_framebuffer_format_) { +void VulkanImmediateDrawer::OnLeavePresenter() { + // Leaving the presenter's submission timeline - await GPU usage completion of + // all draws and texture uploads (which happen before draws) and reset + // submission indices. + VulkanPresenter& vulkan_presenter = + *static_cast(presenter()); + vulkan_presenter.AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + + for (VulkanImmediateTexture* texture : textures_) { + texture->last_usage_submission_ = 0; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + for (SubmittedTextureUploadBuffer& submitted_texture_upload_buffer : + texture_upload_buffers_submitted_) { + dfn.vkDestroyBuffer(device, submitted_texture_upload_buffer.buffer, + nullptr); + dfn.vkFreeMemory(device, submitted_texture_upload_buffer.buffer_memory, + nullptr); + } + + vertex_buffer_pool_->ChangeSubmissionTimeline(); + + last_paint_submission_index_ = 0; + last_completed_submission_index_ = 0; +} + +bool VulkanImmediateDrawer::EnsurePipelinesCreatedForCurrentRenderPass() { + const VulkanUIDrawContext& vulkan_ui_draw_context = + *static_cast(ui_draw_context()); + VkFormat render_pass_format = vulkan_ui_draw_context.render_pass_format(); + + if (render_pass_format == pipeline_framebuffer_format_) { // Either created, or failed to create once (don't try to create every // frame). return pipeline_triangle_ != VK_NULL_HANDLE && pipeline_line_ != VK_NULL_HANDLE; } - VkRenderPass swap_render_pass = context_.swap_render_pass(); - if (swap_surface_format == VK_FORMAT_UNDEFINED || - swap_render_pass == VK_NULL_HANDLE) { - // Not ready yet. - return false; + + if (last_paint_submission_index_ && pipeline_triangle_ != VK_NULL_HANDLE && + pipeline_line_ != VK_NULL_HANDLE) { + // Make sure it's safe to delete the pipelines. + VulkanPresenter& vulkan_presenter = + *static_cast(presenter()); + vulkan_presenter.AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); } - const VulkanProvider& provider = context_.GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Safe to destroy the pipelines now - if the render pass was recreated, // completion of its usage has already been awaited. util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_line_); util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_triangle_); // If creation fails now, don't try to create every frame. - pipeline_framebuffer_format_ = swap_surface_format; + pipeline_framebuffer_format_ = render_pass_format; // Triangle pipeline. VkPipelineShaderStageCreateInfo stages[2] = {}; stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - stages[0].module = util::CreateShaderModule(provider, immediate_vert, + stages[0].module = util::CreateShaderModule(provider_, immediate_vert, sizeof(immediate_vert)); if (stages[0].module == VK_NULL_HANDLE) { - XELOGE("Failed to create the immediate drawer Vulkan vertex shader module"); + XELOGE("VulkanImmediateDrawer: Failed to create the vertex shader module"); return false; } stages[0].pName = "main"; stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - stages[1].module = util::CreateShaderModule(provider, immediate_frag, + stages[1].module = util::CreateShaderModule(provider_, immediate_frag, sizeof(immediate_frag)); if (stages[1].module == VK_NULL_HANDLE) { XELOGE( - "Failed to create the immediate drawer Vulkan fragment shader module"); + "VulkanImmediateDrawer: Failed to create the fragment shader module"); dfn.vkDestroyShaderModule(device, stages[0].module, nullptr); return false; } @@ -621,26 +661,17 @@ bool VulkanImmediateDrawer::EnsurePipelinesCreated() { color_blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; color_blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD; - // Don't change alpha (always 1). - color_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; color_blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; color_blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD; - color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT; - VkPipelineColorBlendStateCreateInfo color_blend_state; + color_blend_attachment_state.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + VkPipelineColorBlendStateCreateInfo color_blend_state = {}; color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - color_blend_state.pNext = nullptr; - color_blend_state.flags = 0; - color_blend_state.logicOpEnable = VK_FALSE; - color_blend_state.logicOp = VK_LOGIC_OP_NO_OP; color_blend_state.attachmentCount = 1; color_blend_state.pAttachments = &color_blend_attachment_state; - color_blend_state.blendConstants[0] = 1.0f; - color_blend_state.blendConstants[1] = 1.0f; - color_blend_state.blendConstants[2] = 1.0f; - color_blend_state.blendConstants[3] = 1.0f; static const VkDynamicState dynamic_states[] = { VK_DYNAMIC_STATE_VIEWPORT, @@ -669,15 +700,15 @@ bool VulkanImmediateDrawer::EnsurePipelinesCreated() { pipeline_create_info.pColorBlendState = &color_blend_state; pipeline_create_info.pDynamicState = &dynamic_state; pipeline_create_info.layout = pipeline_layout_; - pipeline_create_info.renderPass = swap_render_pass; + pipeline_create_info.renderPass = vulkan_ui_draw_context.render_pass(); pipeline_create_info.subpass = 0; pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_create_info.basePipelineIndex = -1; + pipeline_create_info.basePipelineIndex = UINT32_MAX; if (dfn.vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &pipeline_triangle_) != VK_SUCCESS) { XELOGE( - "Failed to create the immediate drawer triangle list Vulkan pipeline"); + "VulkanImmediateDrawer: Failed to create the triangle list pipeline"); dfn.vkDestroyShaderModule(device, stages[1].module, nullptr); dfn.vkDestroyShaderModule(device, stages[0].module, nullptr); return false; @@ -696,7 +727,7 @@ bool VulkanImmediateDrawer::EnsurePipelinesCreated() { dfn.vkDestroyShaderModule(device, stages[1].module, nullptr); dfn.vkDestroyShaderModule(device, stages[0].module, nullptr); if (pipeline_line_create_result != VK_SUCCESS) { - XELOGE("Failed to create the immediate drawer line list Vulkan pipeline"); + XELOGE("VulkanImmediateDrawer: Failed to create the line list pipeline"); dfn.vkDestroyPipeline(device, pipeline_triangle_, nullptr); pipeline_triangle_ = VK_NULL_HANDLE; return false; @@ -719,9 +750,8 @@ uint32_t VulkanImmediateDrawer::AllocateTextureDescriptor() { return (pool->index << 6) | local_index; } - const VulkanProvider& provider = context_.GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkDescriptorSetAllocateInfo allocate_info; allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; @@ -770,7 +800,7 @@ uint32_t VulkanImmediateDrawer::AllocateTextureDescriptor() { if (dfn.vkCreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool) != VK_SUCCESS) { XELOGE( - "Failed to create an immediate drawer Vulkan combined image sampler " + "VulkanImmediateDrawer: Failed to create a combined image sampler " "descriptor pool with {} descriptors", TextureDescriptorPool::kDescriptorCount); return UINT32_MAX; @@ -780,7 +810,7 @@ uint32_t VulkanImmediateDrawer::AllocateTextureDescriptor() { if (dfn.vkAllocateDescriptorSets(device, &allocate_info, &descriptor_set) != VK_SUCCESS) { XELOGE( - "Failed to allocate an immediate drawer Vulkan combined image sampler " + "VulkanImmediateDrawer: Failed to allocate a combined image sampler " "descriptor"); dfn.vkDestroyDescriptorPool(device, descriptor_pool, nullptr); return UINT32_MAX; @@ -831,9 +861,8 @@ bool VulkanImmediateDrawer::CreateTextureResource( bool is_repeated, const uint8_t* data, VulkanImmediateTexture::Resource& resource_out, size_t& pending_upload_index_out) { - const VulkanProvider& provider = context_.GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Create the image and the descriptor. @@ -857,55 +886,14 @@ bool VulkanImmediateDrawer::CreateTextureResource( image_create_info.pQueueFamilyIndices = nullptr; image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImage image; - if (dfn.vkCreateImage(device, &image_create_info, nullptr, &image) != - VK_SUCCESS) { - XELOGE( - "Failed to create a Vulkan image for a {}x{} immediate drawer texture", - width, height); - return false; - } - - VkMemoryAllocateInfo image_memory_allocate_info; - VkMemoryRequirements image_memory_requirements; - dfn.vkGetImageMemoryRequirements(device, image, &image_memory_requirements); - if (!xe::bit_scan_forward(image_memory_requirements.memoryTypeBits & - provider.memory_types_device_local(), - &image_memory_allocate_info.memoryTypeIndex)) { - XELOGE( - "Failed to get a device-local memory type for a {}x{} immediate " - "drawer Vulkan image", - width, height); - dfn.vkDestroyImage(device, image, nullptr); - return false; - } - image_memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - VkMemoryDedicatedAllocateInfoKHR image_memory_dedicated_allocate_info; - if (provider.device_extensions().khr_dedicated_allocation) { - image_memory_dedicated_allocate_info.sType = - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; - image_memory_dedicated_allocate_info.pNext = nullptr; - image_memory_dedicated_allocate_info.image = image; - image_memory_dedicated_allocate_info.buffer = VK_NULL_HANDLE; - image_memory_allocate_info.pNext = &image_memory_dedicated_allocate_info; - } else { - image_memory_allocate_info.pNext = nullptr; - } - image_memory_allocate_info.allocationSize = image_memory_requirements.size; VkDeviceMemory image_memory; - if (dfn.vkAllocateMemory(device, &image_memory_allocate_info, nullptr, - &image_memory) != VK_SUCCESS) { + if (!util::CreateDedicatedAllocationImage(provider_, image_create_info, + util::MemoryPurpose::kDeviceLocal, + image, image_memory)) { XELOGE( - "Failed to allocate memory for a {}x{} immediate drawer Vulkan " - "image", + "VulkanImmediateDrawer: Failed to create an image with dedicated " + "memory for a {}x{} texture", width, height); - dfn.vkDestroyImage(device, image, nullptr); - return false; - } - if (dfn.vkBindImageMemory(device, image, image_memory, 0) != VK_SUCCESS) { - XELOGE("Failed to bind memory to a {}x{} immediate drawer Vulkan image", - width, height); - dfn.vkDestroyImage(device, image, nullptr); - dfn.vkFreeMemory(device, image_memory, nullptr); return false; } @@ -928,7 +916,7 @@ bool VulkanImmediateDrawer::CreateTextureResource( if (dfn.vkCreateImageView(device, &image_view_create_info, nullptr, &image_view) != VK_SUCCESS) { XELOGE( - "Failed to create an image view for a {}x{} immediate drawer Vulkan " + "VulkanImmediateDrawer: Failed to create an image view for a {}x{} " "image", width, height); dfn.vkDestroyImage(device, image, nullptr); @@ -939,9 +927,7 @@ bool VulkanImmediateDrawer::CreateTextureResource( uint32_t descriptor_index = AllocateTextureDescriptor(); if (descriptor_index == UINT32_MAX) { XELOGE( - "Failed to allocate a Vulkan descriptor for a {}x{} immediate drawer " - "texture", - width, height); + "VulkanImmediateDrawer: Failed to allocate a descriptor for an image"); dfn.vkDestroyImageView(device, image_view, nullptr); dfn.vkDestroyImage(device, image, nullptr); dfn.vkFreeMemory(device, image_memory, nullptr); @@ -956,7 +942,7 @@ bool VulkanImmediateDrawer::CreateTextureResource( host_sampler = is_repeated ? VulkanProvider::HostSampler::kNearestRepeat : VulkanProvider::HostSampler::kNearestClamp; } - descriptor_image_info.sampler = provider.GetHostSampler(host_sampler); + descriptor_image_info.sampler = provider_.GetHostSampler(host_sampler); descriptor_image_info.imageView = image_view; descriptor_image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkWriteDescriptorSet descriptor_write; @@ -982,12 +968,12 @@ bool VulkanImmediateDrawer::CreateTextureResource( size_t data_size = sizeof(uint32_t) * width * height; uint32_t upload_buffer_memory_type; if (!util::CreateDedicatedAllocationBuffer( - provider, VkDeviceSize(data_size), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - util::MemoryPurpose::kUpload, upload_buffer, upload_buffer_memory, - &upload_buffer_memory_type)) { + provider_, VkDeviceSize(data_size), + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, util::MemoryPurpose::kUpload, + upload_buffer, upload_buffer_memory, &upload_buffer_memory_type)) { XELOGE( - "Failed to create a Vulkan upload buffer for a {}x{} immediate " - "drawer texture", + "VulkanImmediateDrawer: Failed to create an upload buffer for a " + "{}x{} image", width, height); FreeTextureDescriptor(descriptor_index); dfn.vkDestroyImageView(device, image_view, nullptr); @@ -999,8 +985,8 @@ bool VulkanImmediateDrawer::CreateTextureResource( if (dfn.vkMapMemory(device, upload_buffer_memory, 0, VK_WHOLE_SIZE, 0, &upload_buffer_mapping) != VK_SUCCESS) { XELOGE( - "Failed to map Vulkan upload buffer memory for a {}x{} immediate " - "drawer texture", + "VulkanImmediateDrawer: Failed to map upload buffer memory for a " + "{}x{} image", width, height); dfn.vkDestroyBuffer(device, upload_buffer, nullptr); dfn.vkFreeMemory(device, upload_buffer_memory, nullptr); @@ -1011,7 +997,7 @@ bool VulkanImmediateDrawer::CreateTextureResource( return false; } std::memcpy(upload_buffer_mapping, data, data_size); - util::FlushMappedMemoryRange(provider, upload_buffer_memory, + util::FlushMappedMemoryRange(provider_, upload_buffer_memory, upload_buffer_memory_type); dfn.vkUnmapMemory(device, upload_buffer_memory); } @@ -1038,9 +1024,8 @@ bool VulkanImmediateDrawer::CreateTextureResource( void VulkanImmediateDrawer::DestroyTextureResource( VulkanImmediateTexture::Resource& resource) { FreeTextureDescriptor(resource.descriptor_index); - const VulkanProvider& provider = context_.GetVulkanProvider(); - const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); - VkDevice device = provider.device(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); dfn.vkDestroyImageView(device, resource.image_view, nullptr); dfn.vkDestroyImage(device, resource.image, nullptr); dfn.vkFreeMemory(device, resource.memory, nullptr); @@ -1070,7 +1055,7 @@ void VulkanImmediateDrawer::OnImmediateTextureDestroyed( textures_.pop_back(); // Destroy immediately or queue for destruction if in use. - if (texture.last_usage_submission_ > context_.swap_submission_completed()) { + if (texture.last_usage_submission_ > last_completed_submission_index_) { textures_deleted_.emplace_back( std::make_pair(texture.resource_, texture.last_usage_submission_)); } else { diff --git a/src/xenia/ui/vulkan/vulkan_immediate_drawer.h b/src/xenia/ui/vulkan/vulkan_immediate_drawer.h index 85fbe8731..ca087e1cb 100644 --- a/src/xenia/ui/vulkan/vulkan_immediate_drawer.h +++ b/src/xenia/ui/vulkan/vulkan_immediate_drawer.h @@ -23,15 +23,19 @@ namespace xe { namespace ui { namespace vulkan { -class VulkanContext; - class VulkanImmediateDrawer : public ImmediateDrawer { public: - VulkanImmediateDrawer(VulkanContext& graphics_context); - ~VulkanImmediateDrawer() override; + static std::unique_ptr Create( + const VulkanProvider& provider) { + auto immediate_drawer = std::unique_ptr( + new VulkanImmediateDrawer(provider)); + if (!immediate_drawer->Initialize()) { + return nullptr; + } + return std::move(immediate_drawer); + } - bool Initialize(); - void Shutdown(); + ~VulkanImmediateDrawer(); std::unique_ptr CreateTexture(uint32_t width, uint32_t height, @@ -39,16 +43,20 @@ class VulkanImmediateDrawer : public ImmediateDrawer { bool is_repeated, const uint8_t* data) override; - void Begin(int render_target_width, int render_target_height) override; + void Begin(UIDrawContext& ui_draw_context, float coordinate_space_width, + float coordinate_space_height) override; void BeginDrawBatch(const ImmediateDrawBatch& batch) override; void Draw(const ImmediateDraw& draw) override; void EndDrawBatch() override; void End() override; + protected: + void OnLeavePresenter() override; + private: struct PushConstants { struct Vertex { - float viewport_size_inv[2]; + float coordinate_space_size_inv[2]; } vertex; }; @@ -88,7 +96,10 @@ class VulkanImmediateDrawer : public ImmediateDrawer { TextureDescriptorPool* recycled_next; }; - bool EnsurePipelinesCreated(); + VulkanImmediateDrawer(const VulkanProvider& provider) : provider_(provider) {} + bool Initialize(); + + bool EnsurePipelinesCreatedForCurrentRenderPass(); // Allocates a combined image sampler in a pool and returns its index, or // UINT32_MAX in case of failure. @@ -106,7 +117,7 @@ class VulkanImmediateDrawer : public ImmediateDrawer { void DestroyTextureResource(VulkanImmediateTexture::Resource& resource); void OnImmediateTextureDestroyed(VulkanImmediateTexture& texture); - VulkanContext& context_; + const VulkanProvider& provider_; // Combined image sampler pools for textures. VkDescriptorSetLayout texture_descriptor_set_layout_; @@ -137,14 +148,21 @@ class VulkanImmediateDrawer : public ImmediateDrawer { std::vector> textures_deleted_; - VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE; - std::unique_ptr vertex_buffer_pool_; + VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE; + VkFormat pipeline_framebuffer_format_ = VK_FORMAT_UNDEFINED; VkPipeline pipeline_triangle_ = VK_NULL_HANDLE; VkPipeline pipeline_line_ = VK_NULL_HANDLE; + // The submission index within the current Begin (or the last, if outside + // one). + uint64_t last_paint_submission_index_ = 0; + // Completed submission index as of the latest Begin, to coarsely skip delayed + // texture deletion. + uint64_t last_completed_submission_index_ = 0; + VkCommandBuffer current_command_buffer_ = VK_NULL_HANDLE; VkExtent2D current_render_target_extent_; VkRect2D current_scissor_; diff --git a/src/xenia/ui/vulkan/vulkan_presenter.cc b/src/xenia/ui/vulkan/vulkan_presenter.cc new file mode 100644 index 000000000..64a665c48 --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_presenter.cc @@ -0,0 +1,2548 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/vulkan/vulkan_presenter.h" + +#include +#include +#include +#include +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/cvar.h" +#include "xenia/base/logging.h" +#include "xenia/base/math.h" +#include "xenia/base/platform.h" +#include "xenia/ui/vulkan/vulkan_util.h" + +#if XE_PLATFORM_ANDROID +#include "xenia/ui/surface_android.h" +#endif +#if XE_PLATFORM_GNU_LINUX +#include "xenia/ui/surface_gnulinux.h" +#endif +#if XE_PLATFORM_WIN32 +#include "xenia/ui/surface_win.h" +#endif + +// Note: If the priorities in the description are changed, update the actual +// present mode selection logic. +DEFINE_bool( + vulkan_allow_present_mode_immediate, true, + "When available, allow the immediate presentation mode (1st priority), " + "offering the lowest latency with the possibility of tearing in certain " + "cases, and, depending on the configuration, variable refresh rate.", + "Vulkan"); +DEFINE_bool( + vulkan_allow_present_mode_mailbox, true, + "When available, allow the mailbox presentation mode (2nd priority), " + "offering low latency without the possibility of tearing.", + "Vulkan"); +DEFINE_bool( + vulkan_allow_present_mode_fifo_relaxed, true, + "When available, allow the relaxed first-in-first-out presentation mode " + "(3rd priority), which causes waiting for host display vertical sync, but " + "may present with tearing if frames don't meet the host display refresh " + "rate.", + "Vulkan"); + +namespace xe { +namespace ui { +namespace vulkan { + +// Generated with `xb buildshaders`. +namespace shaders { +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h" +} // namespace shaders + +VulkanPresenter::PaintContext::Submission::~Submission() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + if (draw_command_pool_ != VK_NULL_HANDLE) { + dfn.vkDestroyCommandPool(device, draw_command_pool_, nullptr); + } + + if (present_semaphore_ != VK_NULL_HANDLE) { + dfn.vkDestroySemaphore(device, present_semaphore_, nullptr); + } + if (acquire_semaphore_ != VK_NULL_HANDLE) { + dfn.vkDestroySemaphore(device, acquire_semaphore_, nullptr); + } +} + +bool VulkanPresenter::PaintContext::Submission::Initialize() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkSemaphoreCreateInfo semaphore_create_info; + semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semaphore_create_info.pNext = nullptr; + semaphore_create_info.flags = 0; + if (dfn.vkCreateSemaphore(device, &semaphore_create_info, nullptr, + &acquire_semaphore_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a swapchain image acquisition " + "semaphore"); + return false; + } + if (dfn.vkCreateSemaphore(device, &semaphore_create_info, nullptr, + &present_semaphore_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a swapchain image presentation " + "semaphore"); + return false; + } + + VkCommandPoolCreateInfo command_pool_create_info; + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + command_pool_create_info.queueFamilyIndex = + provider_.queue_family_graphics_compute(); + if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr, + &draw_command_pool_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a command pool for drawing to a " + "swapchain"); + return false; + } + VkCommandBufferAllocateInfo command_buffer_allocate_info; + command_buffer_allocate_info.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_allocate_info.pNext = nullptr; + command_buffer_allocate_info.commandPool = draw_command_pool_; + command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_allocate_info.commandBufferCount = 1; + if (dfn.vkAllocateCommandBuffers(device, &command_buffer_allocate_info, + &draw_command_buffer_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to allocate a command buffer for drawing to a " + "swapchain"); + return false; + } + + return true; +} + +VulkanPresenter::~VulkanPresenter() { + // Destroy the swapchain after its images are not used for drawing anymore. + // This is a confusing part in Vulkan, as vkQueuePresentKHR doesn't signal a + // fence clearly indicating when it's safe to destroy a swapchain, so we + // assume that its lifetime is tracked internally in the WSI. This is also + // done before destroying the semaphore awaited by vkQueuePresentKHR, hoping + // that it will prevent the destruction during the semaphore wait in + // vkQueuePresentKHR execution (or between the vkQueueSubmit semaphore signal + // and the vkQueuePresentKHR semaphore wait). + // This will await completion of all paint submissions also. + paint_context_.DestroySwapchainAndVulkanSurface(); + + // Await completion of the usage of everything before destroying anything + // (paint submission completion already awaited). + // From most likely the latest to most likely the earliest to be signaled, so + // just one sleep will likely be needed. + ui_submission_tracker_.Shutdown(); + guest_output_image_refresher_submission_tracker_.Shutdown(); + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + if (paint_context_.swapchain_render_pass != VK_NULL_HANDLE) { + dfn.vkDestroyRenderPass(device, paint_context_.swapchain_render_pass, + nullptr); + } + + for (const PaintContext::UISetupCommandBuffer& ui_setup_command_buffer : + paint_context_.ui_setup_command_buffers) { + dfn.vkDestroyCommandPool(device, ui_setup_command_buffer.command_pool, + nullptr); + } + + for (VkFramebuffer& framebuffer : + paint_context_.guest_output_intermediate_framebuffers) { + util::DestroyAndNullHandle(dfn.vkDestroyFramebuffer, device, framebuffer); + } + util::DestroyAndNullHandle(dfn.vkDestroyDescriptorPool, device, + paint_context_.guest_output_descriptor_pool); + for (PaintContext::GuestOutputPaintPipeline& guest_output_paint_pipeline : + paint_context_.guest_output_paint_pipelines) { + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, + guest_output_paint_pipeline.swapchain_pipeline); + util::DestroyAndNullHandle( + dfn.vkDestroyPipeline, device, + guest_output_paint_pipeline.intermediate_pipeline); + } + + util::DestroyAndNullHandle(dfn.vkDestroyRenderPass, device, + guest_output_intermediate_render_pass_); + for (VkShaderModule& shader_module : guest_output_paint_fs_) { + util::DestroyAndNullHandle(dfn.vkDestroyShaderModule, device, + shader_module); + } + util::DestroyAndNullHandle(dfn.vkDestroyShaderModule, device, + guest_output_paint_vs_); + for (VkPipelineLayout& pipeline_layout : + guest_output_paint_pipeline_layouts_) { + util::DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, device, + pipeline_layout); + } + util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, device, + guest_output_paint_image_descriptor_set_layout_); +} + +Surface::TypeFlags VulkanPresenter::GetSupportedSurfaceTypes() const { + if (!provider_.device_extensions().khr_swapchain) { + return 0; + } + return GetSurfaceTypesSupportedByInstance(provider_.instance_extensions()); +} + +bool VulkanPresenter::CaptureGuestOutput(RawImage& image_out) { + std::shared_ptr guest_output_image; + { + uint32_t guest_output_mailbox_index; + std::unique_lock guest_output_consumer_lock( + ConsumeGuestOutput(guest_output_mailbox_index, nullptr, nullptr)); + if (guest_output_mailbox_index != UINT32_MAX) { + assert_true(guest_output_images_[guest_output_mailbox_index] + .ever_successfully_refreshed); + guest_output_image = + guest_output_images_[guest_output_mailbox_index].image; + } + // Incremented the reference count of the guest output image - safe to leave + // the consumer critical section now. + } + if (!guest_output_image) { + return false; + } + + VkExtent2D image_extent = guest_output_image->extent(); + size_t pixel_count = size_t(image_extent.width) * image_extent.height; + VkDeviceSize buffer_size = VkDeviceSize(sizeof(uint32_t) * pixel_count); + VkBuffer buffer; + VkDeviceMemory buffer_memory; + if (!util::CreateDedicatedAllocationBuffer( + provider_, buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, + util::MemoryPurpose::kReadback, buffer, buffer_memory)) { + XELOGE("VulkanPresenter: Failed to create the guest output capture buffer"); + return false; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + { + VkCommandPoolCreateInfo command_pool_create_info; + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + command_pool_create_info.queueFamilyIndex = + provider_.queue_family_graphics_compute(); + VkCommandPool command_pool; + if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr, + &command_pool) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output capturing " + "command pool"); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + VkCommandBufferAllocateInfo command_buffer_allocate_info; + command_buffer_allocate_info.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_allocate_info.pNext = nullptr; + command_buffer_allocate_info.commandPool = command_pool; + command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_allocate_info.commandBufferCount = 1; + VkCommandBuffer command_buffer; + if (dfn.vkAllocateCommandBuffers(device, &command_buffer_allocate_info, + &command_buffer) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to allocate the guest output capturing " + "command buffer"); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + VkCommandBufferBeginInfo command_buffer_begin_info; + command_buffer_begin_info.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + command_buffer_begin_info.pNext = nullptr; + command_buffer_begin_info.flags = + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + command_buffer_begin_info.pInheritanceInfo = nullptr; + if (dfn.vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info) != + VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to begin recording the guest output " + "capturing command buffer"); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + VkImageMemoryBarrier image_memory_barrier; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = kGuestOutputInternalAccessMask; + image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + image_memory_barrier.oldLayout = kGuestOutputInternalLayout; + image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = guest_output_image->image(); + util::InitializeSubresourceRange(image_memory_barrier.subresourceRange); + dfn.vkCmdPipelineBarrier(command_buffer, kGuestOutputInternalStageMask, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, + nullptr, 1, &image_memory_barrier); + + VkBufferImageCopy buffer_image_copy = {}; + buffer_image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + buffer_image_copy.imageSubresource.layerCount = 1; + buffer_image_copy.imageExtent.width = image_extent.width; + buffer_image_copy.imageExtent.height = image_extent.height; + buffer_image_copy.imageExtent.depth = 1; + dfn.vkCmdCopyImageToBuffer(command_buffer, guest_output_image->image(), + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1, + &buffer_image_copy); + + // A fence doesn't guarantee host visibility and availability. + VkBufferMemoryBarrier buffer_memory_barrier; + buffer_memory_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + buffer_memory_barrier.pNext = nullptr; + buffer_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + buffer_memory_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; + buffer_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + buffer_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + buffer_memory_barrier.buffer = buffer; + buffer_memory_barrier.offset = 0; + buffer_memory_barrier.size = VK_WHOLE_SIZE; + std::swap(image_memory_barrier.srcAccessMask, + image_memory_barrier.dstAccessMask); + std::swap(image_memory_barrier.oldLayout, image_memory_barrier.newLayout); + dfn.vkCmdPipelineBarrier( + command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_HOST_BIT | kGuestOutputInternalStageMask, 0, 0, + nullptr, 1, &buffer_memory_barrier, 1, &image_memory_barrier); + + if (dfn.vkEndCommandBuffer(command_buffer) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to end recording the guest output capturing " + "command buffer"); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + VulkanSubmissionTracker submission_tracker(provider_); + { + VulkanSubmissionTracker::FenceAcquisition fence_acqusition( + submission_tracker.AcquireFenceToAdvanceSubmission()); + if (!fence_acqusition.fence()) { + XELOGE( + "VulkanPresenter: Failed to acquire a fence for guest output " + "capturing"); + fence_acqusition.SubmissionFailedOrDropped(); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + VkResult submit_result; + { + VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(provider_.queue_family_graphics_compute(), + 0)); + submit_result = dfn.vkQueueSubmit( + queue_acquisition.queue, 1, &submit_info, fence_acqusition.fence()); + } + if (submit_result != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to submit the guest output capturing " + "command buffer"); + fence_acqusition.SubmissionFailedOrDropped(); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + } + if (!submission_tracker.AwaitAllSubmissionsCompletion()) { + XELOGE( + "VulkanPresenter: Failed to await the guest output capturing fence"); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + } + + // Don't need the buffer anymore, just its memory. + dfn.vkDestroyBuffer(device, buffer, nullptr); + + void* mapping; + if (dfn.vkMapMemory(device, buffer_memory, 0, VK_WHOLE_SIZE, 0, &mapping) != + VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to map the guest output capture memory"); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + image_out.width = image_extent.width; + image_out.height = image_extent.height; + image_out.stride = sizeof(uint32_t) * image_extent.width; + image_out.data.resize(size_t(buffer_size)); + uint32_t* image_out_pixels = + reinterpret_cast(image_out.data.data()); + for (size_t i = 0; i < pixel_count; ++i) { + image_out_pixels[i] = Packed10bpcRGBTo8bpcBytes( + reinterpret_cast(mapping)[i]); + } + + // Unmapping will be done by freeing. + dfn.vkFreeMemory(device, buffer_memory, nullptr); + + return true; +} + +VkCommandBuffer VulkanPresenter::AcquireUISetupCommandBufferFromUIThread() { + if (paint_context_.ui_setup_command_buffer_current_index != SIZE_MAX) { + return paint_context_ + .ui_setup_command_buffers[paint_context_ + .ui_setup_command_buffer_current_index] + .command_buffer; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkCommandBufferBeginInfo command_buffer_begin_info; + command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + command_buffer_begin_info.pNext = nullptr; + command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + command_buffer_begin_info.pInheritanceInfo = nullptr; + + // Try to reuse an existing command buffer. + if (!paint_context_.ui_setup_command_buffers.empty()) { + uint64_t submission_index_completed = + ui_submission_tracker_.UpdateAndGetCompletedSubmission(); + for (size_t i = 0; i < paint_context_.ui_setup_command_buffers.size(); + ++i) { + PaintContext::UISetupCommandBuffer& ui_setup_command_buffer = + paint_context_.ui_setup_command_buffers[i]; + if (ui_setup_command_buffer.last_usage_submission_index > + submission_index_completed) { + continue; + } + if (dfn.vkResetCommandPool(device, ui_setup_command_buffer.command_pool, + 0) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to reset a UI setup command pool"); + return VK_NULL_HANDLE; + } + if (dfn.vkBeginCommandBuffer(ui_setup_command_buffer.command_buffer, + &command_buffer_begin_info) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to begin UI setup command buffer " + "recording"); + return VK_NULL_HANDLE; + } + paint_context_.ui_setup_command_buffer_current_index = i; + ui_setup_command_buffer.last_usage_submission_index = + ui_submission_tracker_.GetCurrentSubmission(); + return ui_setup_command_buffer.command_buffer; + } + } + + // Create a new command buffer. + VkCommandPoolCreateInfo command_pool_create_info; + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + command_pool_create_info.queueFamilyIndex = + provider_.queue_family_graphics_compute(); + VkCommandPool new_command_pool; + if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr, + &new_command_pool) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a UI setup command pool"); + return VK_NULL_HANDLE; + } + VkCommandBufferAllocateInfo command_buffer_allocate_info; + command_buffer_allocate_info.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_allocate_info.pNext = nullptr; + command_buffer_allocate_info.commandPool = new_command_pool; + command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_allocate_info.commandBufferCount = 1; + VkCommandBuffer new_command_buffer; + if (dfn.vkAllocateCommandBuffers(device, &command_buffer_allocate_info, + &new_command_buffer) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to allocate a UI setup command buffer"); + dfn.vkDestroyCommandPool(device, new_command_pool, nullptr); + return VK_NULL_HANDLE; + } + if (dfn.vkBeginCommandBuffer(new_command_buffer, + &command_buffer_begin_info) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to begin UI setup command buffer recording"); + dfn.vkDestroyCommandPool(device, new_command_pool, nullptr); + return VK_NULL_HANDLE; + } + paint_context_.ui_setup_command_buffer_current_index = + paint_context_.ui_setup_command_buffers.size(); + paint_context_.ui_setup_command_buffers.emplace_back( + new_command_pool, new_command_buffer, + ui_submission_tracker_.GetCurrentSubmission()); + return new_command_buffer; +} + +Presenter::SurfacePaintConnectResult +VulkanPresenter::ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) { + const VulkanProvider::InstanceFunctions& ifn = provider_.ifn(); + VkInstance instance = provider_.instance(); + VkPhysicalDevice physical_device = provider_.physical_device(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkFormat new_swapchain_format; + + // ConnectOrReconnectToSurfaceFromUIThread may be called only for the + // ui::Surface of the current swapchain or when the old swapchain and + // VkSurface have, if the ui::Surface is the same, try using the existing + // VkSurface and creating the swapchain smoothly from the existing one - if + // this doesn't succeed, start from scratch. + // The retirement or destruction of the swapchain here will also cause + // awaiting completion of the usage of the swapchain and the surface on the + // GPU. + if (paint_context_.vulkan_surface != VK_NULL_HANDLE) { + VkSwapchainKHR old_swapchain = + paint_context_.PrepareForSwapchainRetirement(); + bool surface_unusable; + paint_context_.swapchain = PaintContext::CreateSwapchainForVulkanSurface( + provider_, paint_context_.vulkan_surface, new_surface_width, + new_surface_height, old_swapchain, paint_context_.present_queue_family, + new_swapchain_format, paint_context_.swapchain_extent, + paint_context_.swapchain_is_fifo, surface_unusable); + // Destroy the old swapchain that may be retired now. + if (old_swapchain != VK_NULL_HANDLE) { + dfn.vkDestroySwapchainKHR(device, old_swapchain, nullptr); + } + if (paint_context_.swapchain == VK_NULL_HANDLE) { + // Couldn't create the swapchain for the existing surface - start over. + paint_context_.DestroySwapchainAndVulkanSurface(); + } + } + + // If failed to create the swapchain for the previous surface, recreate the + // surface and create the new swapchain. + if (paint_context_.swapchain == VK_NULL_HANDLE) { + // DestroySwapchainAndVulkanSurface should have been called previously. + assert_true(paint_context_.vulkan_surface == VK_NULL_HANDLE); + Surface::TypeIndex surface_type = new_surface.GetType(); + // Check if the surface type is supported according to the Vulkan + // extensions. + if (!(GetSupportedSurfaceTypes() & + (Surface::TypeFlags(1) << surface_type))) { + XELOGE( + "VulkanPresenter: Tried to create a Vulkan surface for an " + "unsupported Xenia surface type"); + return SurfacePaintConnectResult::kFailureSurfaceUnusable; + } + VkResult vulkan_surface_create_result = VK_ERROR_UNKNOWN; + switch (surface_type) { +#if XE_PLATFORM_ANDROID + case Surface::kTypeIndex_AndroidNativeWindow: { + auto& android_native_window_surface = + static_cast(new_surface); + VkAndroidSurfaceCreateInfoKHR surface_create_info; + surface_create_info.sType = + VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + surface_create_info.pNext = nullptr; + surface_create_info.flags = 0; + surface_create_info.window = android_native_window_surface.window(); + vulkan_surface_create_result = ifn.vkCreateAndroidSurfaceKHR( + instance, &surface_create_info, nullptr, + &paint_context_.vulkan_surface); + } break; +#endif +#if XE_PLATFORM_GNU_LINUX + case Surface::kTypeIndex_XcbWindow: { + auto& xcb_window_surface = + static_cast(new_surface); + VkXcbSurfaceCreateInfoKHR surface_create_info; + surface_create_info.sType = + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + surface_create_info.pNext = nullptr; + surface_create_info.flags = 0; + surface_create_info.connection = xcb_window_surface.connection(); + surface_create_info.window = xcb_window_surface.window(); + vulkan_surface_create_result = + ifn.vkCreateXcbSurfaceKHR(instance, &surface_create_info, nullptr, + &paint_context_.vulkan_surface); + } break; +#endif +#if XE_PLATFORM_WIN32 + case Surface::kTypeIndex_Win32Hwnd: { + auto& win32_hwnd_surface = + static_cast(new_surface); + VkWin32SurfaceCreateInfoKHR surface_create_info; + surface_create_info.sType = + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surface_create_info.pNext = nullptr; + surface_create_info.flags = 0; + surface_create_info.hinstance = win32_hwnd_surface.hinstance(); + surface_create_info.hwnd = win32_hwnd_surface.hwnd(); + vulkan_surface_create_result = + ifn.vkCreateWin32SurfaceKHR(instance, &surface_create_info, nullptr, + &paint_context_.vulkan_surface); + } break; +#endif + default: + assert_unhandled_case(surface_type); + XELOGE( + "VulkanPresenter: Tried to create a Vulkan surface for an " + "unknown Xenia surface type"); + return SurfacePaintConnectResult::kFailureSurfaceUnusable; + } + if (vulkan_surface_create_result != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a Vulkan surface"); + return SurfacePaintConnectResult::kFailure; + } + bool surface_unusable; + paint_context_.swapchain = PaintContext::CreateSwapchainForVulkanSurface( + provider_, paint_context_.vulkan_surface, new_surface_width, + new_surface_height, VK_NULL_HANDLE, paint_context_.present_queue_family, + new_swapchain_format, paint_context_.swapchain_extent, + paint_context_.swapchain_is_fifo, surface_unusable); + if (paint_context_.swapchain == VK_NULL_HANDLE) { + // Failed to create the swapchain for the new Vulkan surface - destroy the + // Vulkan surface. + ifn.vkDestroySurfaceKHR(instance, paint_context_.vulkan_surface, nullptr); + paint_context_.vulkan_surface = VK_NULL_HANDLE; + return surface_unusable + ? SurfacePaintConnectResult::kFailureSurfaceUnusable + : SurfacePaintConnectResult::kFailure; + } + // Successfully attached (at least for now). + } + + // From now on, in case of failure, + // paint_context_.DestroySwapchainAndVulkanSurface must be called before + // returning. + + // Update the render pass to the new format. + if (paint_context_.swapchain_render_pass_format != new_swapchain_format) { + util::DestroyAndNullHandle(dfn.vkDestroyRenderPass, device, + paint_context_.swapchain_render_pass); + paint_context_.swapchain_render_pass_format = new_swapchain_format; + } + if (paint_context_.swapchain_render_pass == VK_NULL_HANDLE) { + VkAttachmentDescription render_pass_attachment; + render_pass_attachment.flags = 0; + render_pass_attachment.format = new_swapchain_format; + render_pass_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + render_pass_attachment.loadOp = cvars::present_render_pass_clear + ? VK_ATTACHMENT_LOAD_OP_CLEAR + : VK_ATTACHMENT_LOAD_OP_DONT_CARE; + render_pass_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + render_pass_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + render_pass_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + render_pass_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + render_pass_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + VkAttachmentReference render_pass_color_attachment; + render_pass_color_attachment.attachment = 0; + render_pass_color_attachment.layout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkSubpassDescription render_pass_subpass = {}; + render_pass_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + render_pass_subpass.colorAttachmentCount = 1; + render_pass_subpass.pColorAttachments = &render_pass_color_attachment; + VkSubpassDependency render_pass_dependencies[2]; + render_pass_dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + render_pass_dependencies[0].dstSubpass = 0; + // srcStageMask is the semaphore wait stage. + render_pass_dependencies[0].srcStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + render_pass_dependencies[0].dstStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + render_pass_dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + // The main target can be used for UI drawing at any moment, which requires + // blending, so VK_ACCESS_COLOR_ATTACHMENT_READ_BIT is also included. + render_pass_dependencies[0].dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + render_pass_dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + render_pass_dependencies[1].srcSubpass = 0; + render_pass_dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + render_pass_dependencies[1].srcStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + // Semaphores are signaled at VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT. + render_pass_dependencies[1].dstStageMask = + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + render_pass_dependencies[1].srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + render_pass_dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + render_pass_dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + VkRenderPassCreateInfo render_pass_create_info; + render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + render_pass_create_info.pNext = nullptr; + render_pass_create_info.flags = 0; + render_pass_create_info.attachmentCount = 1; + render_pass_create_info.pAttachments = &render_pass_attachment; + render_pass_create_info.subpassCount = 1; + render_pass_create_info.pSubpasses = &render_pass_subpass; + render_pass_create_info.dependencyCount = + uint32_t(xe::countof(render_pass_dependencies)); + render_pass_create_info.pDependencies = render_pass_dependencies; + VkRenderPass new_render_pass; + if (dfn.vkCreateRenderPass(device, &render_pass_create_info, nullptr, + &new_render_pass) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the render pass for drawing to " + "swapchain images"); + paint_context_.DestroySwapchainAndVulkanSurface(); + return SurfacePaintConnectResult::kFailure; + } + paint_context_.swapchain_render_pass = new_render_pass; + paint_context_.swapchain_render_pass_format = new_swapchain_format; + paint_context_.swapchain_render_pass_clear_load_op = + render_pass_attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR; + } + + // Get the swapchain images. + paint_context_.swapchain_images.clear(); + VkResult swapchain_images_get_result; + for (;;) { + uint32_t swapchain_image_count = + uint32_t(paint_context_.swapchain_images.size()); + bool swapchain_images_were_empty = !swapchain_image_count; + swapchain_images_get_result = dfn.vkGetSwapchainImagesKHR( + device, paint_context_.swapchain, &swapchain_image_count, + swapchain_images_were_empty ? nullptr + : paint_context_.swapchain_images.data()); + // If the original swapchain image count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (swapchain_images_get_result == VK_SUCCESS || + swapchain_images_get_result == VK_INCOMPLETE) { + paint_context_.swapchain_images.resize(swapchain_image_count); + if (swapchain_images_get_result == VK_SUCCESS && + (!swapchain_images_were_empty || !swapchain_image_count)) { + break; + } + } else { + break; + } + } + if (swapchain_images_get_result != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to get swapchain images"); + paint_context_.DestroySwapchainAndVulkanSurface(); + return SurfacePaintConnectResult::kFailure; + } + + // Create the image views and the framebuffers. + assert_true(paint_context_.swapchain_framebuffers.empty()); + paint_context_.swapchain_framebuffers.reserve( + paint_context_.swapchain_images.size()); + VkImageViewCreateInfo image_view_create_info; + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = nullptr; + image_view_create_info.flags = 0; + image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + image_view_create_info.format = new_swapchain_format; + image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.subresourceRange.aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT; + image_view_create_info.subresourceRange.baseMipLevel = 0; + image_view_create_info.subresourceRange.levelCount = 1; + image_view_create_info.subresourceRange.baseArrayLayer = 0; + image_view_create_info.subresourceRange.layerCount = 1; + VkImageView image_view; + VkFramebufferCreateInfo framebuffer_create_info; + framebuffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebuffer_create_info.pNext = nullptr; + framebuffer_create_info.flags = 0; + framebuffer_create_info.renderPass = paint_context_.swapchain_render_pass; + framebuffer_create_info.attachmentCount = 1; + framebuffer_create_info.pAttachments = &image_view; + framebuffer_create_info.width = paint_context_.swapchain_extent.width; + framebuffer_create_info.height = paint_context_.swapchain_extent.height; + framebuffer_create_info.layers = 1; + for (VkImage image : paint_context_.swapchain_images) { + image_view_create_info.image = image; + if (dfn.vkCreateImageView(device, &image_view_create_info, nullptr, + &image_view) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a swapchain image view"); + paint_context_.DestroySwapchainAndVulkanSurface(); + return SurfacePaintConnectResult::kFailure; + } + VkFramebuffer framebuffer; + if (dfn.vkCreateFramebuffer(device, &framebuffer_create_info, nullptr, + &framebuffer) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a swapchain framebuffer"); + dfn.vkDestroyImageView(device, image_view, nullptr); + paint_context_.DestroySwapchainAndVulkanSurface(); + return SurfacePaintConnectResult::kFailure; + } + paint_context_.swapchain_framebuffers.emplace_back(image_view, framebuffer); + } + + is_vsync_implicit_out = paint_context_.swapchain_is_fifo; + return SurfacePaintConnectResult::kSuccess; +} + +void VulkanPresenter::DisconnectPaintingFromSurfaceFromUIThreadImpl() { + paint_context_.DestroySwapchainAndVulkanSurface(); +} + +bool VulkanPresenter::RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out_ref) { + assert_not_zero(frontbuffer_width); + assert_not_zero(frontbuffer_height); + VkExtent2D max_framebuffer_extent = + util::GetMax2DFramebufferExtent(provider_); + if (frontbuffer_width > max_framebuffer_extent.width || + frontbuffer_height > max_framebuffer_extent.height) { + // Writing the guest output isn't supposed to rescale, and a guest texture + // exceeding the maximum size won't be loadable anyway. + return false; + } + + GuestOutputImageInstance& image_instance = + guest_output_images_[mailbox_index]; + if (image_instance.image && + (image_instance.image->extent().width != frontbuffer_width || + image_instance.image->extent().height != frontbuffer_height)) { + guest_output_image_refresher_submission_tracker_.AwaitSubmissionCompletion( + image_instance.last_refresher_submission); + image_instance.image.reset(); + } + if (!image_instance.image) { + std::unique_ptr new_image = GuestOutputImage::Create( + provider_, frontbuffer_width, frontbuffer_height); + if (!new_image) { + return false; + } + image_instance.SetToNewImage(std::move(new_image), + guest_output_image_next_version_++); + } + + VulkanGuestOutputRefreshContext context( + is_8bpc_out_ref, image_instance.image->image(), + image_instance.image->view(), image_instance.version, + image_instance.ever_successfully_refreshed); + bool refresher_succeeded = refresher(context); + if (refresher_succeeded) { + image_instance.ever_successfully_refreshed = true; + } + // Even if the refresher has returned false, it still might have submitted + // some commands referencing the image. It's better to put an excessive + // signal and wait slightly longer, for nothing important, while shutting down + // than to destroy the image while it's still in use. + image_instance.last_refresher_submission = + guest_output_image_refresher_submission_tracker_.GetCurrentSubmission(); + // No need to make the refresher signal the fence by itself - signal it here + // instead to have more control: + // "Fence signal operations that are defined by vkQueueSubmit additionally + // include in the first synchronization scope all commands that occur earlier + // in submission order." + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + { + VulkanSubmissionTracker::FenceAcquisition fence_acqusition( + guest_output_image_refresher_submission_tracker_ + .AcquireFenceToAdvanceSubmission()); + VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(provider_.queue_family_graphics_compute(), 0)); + if (dfn.vkQueueSubmit(queue_acquisition.queue, 0, nullptr, + fence_acqusition.fence()) != VK_SUCCESS) { + fence_acqusition.SubmissionSucceededSignalFailed(); + } + } + + return refresher_succeeded; +} + +VkSwapchainKHR VulkanPresenter::PaintContext::CreateSwapchainForVulkanSurface( + const VulkanProvider& provider, VkSurfaceKHR surface, uint32_t width, + uint32_t height, VkSwapchainKHR old_swapchain, + uint32_t& present_queue_family_out, VkFormat& image_format_out, + VkExtent2D& image_extent_out, bool& is_fifo_out, + bool& ui_surface_unusable_out) { + ui_surface_unusable_out = false; + + const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); + VkInstance instance = provider.instance(); + VkPhysicalDevice physical_device = provider.physical_device(); + const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + + // Get surface capabilities. + VkSurfaceCapabilitiesKHR surface_capabilities; + if (ifn.vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + physical_device, surface, &surface_capabilities) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to get Vulkan surface capabilities"); + // Some strange error, try again later. + return VK_NULL_HANDLE; + } + + // First, check if the surface is not zero-area because in this case, the rest + // of the fields in theory may not be informative as the surface doesn't need + // to go to presentation anyway, thus there's no need to return real + // information, and ui_surface_unusable_out (from which it may not be possible + // to recover on certain platforms at all) may be set to true spuriously if + // any checks set it to true. VkSurfaceKHR may have zero-area bounds in some + // window state cases on Windows, for example. Also clamp the requested size + // to the maximum supported by the physical device as long as minImageExtent + // in the instance's WSI allows that (if not, there's no way to satisfy both + // requirements - the maximum 2D framebuffer size on the specific physical + // device, and the minimum swap chain size on the whole instance - fail to + // create until the surface becomes smaller). + VkExtent2D max_framebuffer_extent = util::GetMax2DFramebufferExtent(provider); + VkExtent2D image_extent; + image_extent.width = + std::min(std::max(std::min(width, max_framebuffer_extent.width), + surface_capabilities.minImageExtent.width), + surface_capabilities.maxImageExtent.width); + image_extent.height = + std::min(std::max(std::min(height, max_framebuffer_extent.height), + surface_capabilities.minImageExtent.height), + surface_capabilities.maxImageExtent.height); + if (!image_extent.width || !image_extent.height || + image_extent.width > max_framebuffer_extent.width || + image_extent.height > max_framebuffer_extent.height) { + return VK_NULL_HANDLE; + } + + // Get the queue family for presentation. + uint32_t queue_family_index_present = UINT32_MAX; + const std::vector& queue_families = + provider.queue_families(); + VkBool32 queue_family_present_supported; + // First try the graphics and compute queue, prefer it to avoid the concurrent + // image sharing mode. + uint32_t queue_family_index_graphics_compute = + provider.queue_family_graphics_compute(); + const VulkanProvider::QueueFamily& queue_family_graphics_compute = + queue_families[queue_family_index_graphics_compute]; + if (queue_family_graphics_compute.potentially_supports_present && + queue_family_graphics_compute.queue_count && + ifn.vkGetPhysicalDeviceSurfaceSupportKHR( + physical_device, queue_family_index_graphics_compute, surface, + &queue_family_present_supported) == VK_SUCCESS && + queue_family_present_supported) { + queue_family_index_present = queue_family_index_graphics_compute; + } else { + for (uint32_t i = 0; i < uint32_t(queue_families.size()); ++i) { + const VulkanProvider::QueueFamily& queue_family = queue_families[i]; + if (queue_family.potentially_supports_present && + queue_family.queue_count && + ifn.vkGetPhysicalDeviceSurfaceSupportKHR( + physical_device, i, surface, &queue_family_present_supported) == + VK_SUCCESS && + queue_family_present_supported) { + queue_family_index_present = i; + break; + } + } + } + if (queue_family_index_present == UINT32_MAX) { + // Not unusable though - may become presentable if the window (with the same + // surface) moved to a different display, for instance. + return VK_NULL_HANDLE; + } + + // TODO(Triang3l): Support transforms. + if (!(surface_capabilities.supportedTransforms & + (VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR | + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR))) { + XELOGE( + "VulkanPresenter: The surface doesn't support identity or " + "window-system-controlled transform"); + return VK_NULL_HANDLE; + } + + // Get the surface format. + std::vector surface_formats; + VkResult surface_formats_get_result; + for (;;) { + uint32_t surface_format_count = uint32_t(surface_formats.size()); + bool surface_formats_were_empty = !surface_format_count; + surface_formats_get_result = ifn.vkGetPhysicalDeviceSurfaceFormatsKHR( + physical_device, surface, &surface_format_count, + surface_formats_were_empty ? nullptr : surface_formats.data()); + // If the original presentation mode count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (surface_formats_get_result == VK_SUCCESS || + surface_formats_get_result == VK_INCOMPLETE) { + surface_formats.resize(surface_format_count); + if (surface_formats_get_result == VK_SUCCESS && + (!surface_formats_were_empty || !surface_format_count)) { + break; + } + } else { + break; + } + } + if (surface_formats_get_result != VK_SUCCESS) { + // Assuming any format in case of an error (or as some fallback in case of + // specification violation). + surface_formats.clear(); + } +#if XE_PLATFORM_ANDROID + // Android uses R8G8B8A8. + static const VkFormat kFormat8888Primary = VK_FORMAT_R8G8B8A8_UNORM; + static const VkFormat kFormat8888Secondary = VK_FORMAT_B8G8R8A8_UNORM; +#else + // GNU/Linux X11 and Windows DWM use B8G8R8A8. + static const VkFormat kFormat8888Primary = VK_FORMAT_B8G8R8A8_UNORM; + static const VkFormat kFormat8888Secondary = VK_FORMAT_R8G8B8A8_UNORM; +#endif + VkSurfaceFormatKHR image_format; + if (surface_formats.empty() || + (surface_formats.size() == 1 || + surface_formats[0].format == VK_FORMAT_UNDEFINED)) { + // Can choose any format if the implementation specifies only UNDEFINED. + image_format.format = kFormat8888Primary; + image_format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + } else { + // Pick the sRGB 8888 format preferred by the OS, fall back to any sRGB + // 8888, then to 8888 with an unknown color space, and then to the first + // sRGB available, and then to the first. + auto format_8888_primary_it = surface_formats.cend(); + auto format_8888_secondary_it = surface_formats.cend(); + auto any_non_8888_srgb_it = surface_formats.cend(); + for (auto it = surface_formats.cbegin(); it != surface_formats.cend(); + ++it) { + if (it->format != kFormat8888Primary && + it->format != kFormat8888Secondary) { + if (it->colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR && + any_non_8888_srgb_it == surface_formats.cend()) { + any_non_8888_srgb_it = it; + } + continue; + } + auto& preferred_8888_it = it->format == kFormat8888Primary + ? format_8888_primary_it + : format_8888_secondary_it; + if (preferred_8888_it == surface_formats.cend()) { + // First primary or secondary 8888 encounter. + preferred_8888_it = it; + continue; + } + // Is this a better primary or secondary 8888, that is, this is sRGB, + // while the previous encounter was not? + if (it->colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR && + preferred_8888_it->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + preferred_8888_it = it; + } + } + if (format_8888_primary_it != surface_formats.cend() && + format_8888_secondary_it != surface_formats.cend()) { + // Both the primary and the secondary 8888 formats are available - prefer + // sRGB, if both are sRGB or not, prefer the primary format. + if (format_8888_primary_it->colorSpace == + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR || + format_8888_secondary_it->colorSpace != + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + image_format = *format_8888_primary_it; + } else { + image_format = *format_8888_secondary_it; + } + } else if (format_8888_primary_it != surface_formats.cend()) { + // Only primary 8888. + image_format = *format_8888_primary_it; + } else if (format_8888_secondary_it != surface_formats.cend()) { + // Only secondary 8888. + image_format = *format_8888_secondary_it; + } else if (any_non_8888_srgb_it != surface_formats.cend()) { + // No 8888, but some sRGB format is available. + image_format = *any_non_8888_srgb_it; + } else { + // Just pick any format. + image_format = surface_formats.front(); + } + } + + // Get presentation modes. + std::vector present_modes; + VkResult present_modes_get_result; + for (;;) { + uint32_t present_mode_count = uint32_t(present_modes.size()); + bool present_modes_were_empty = !present_mode_count; + present_modes_get_result = ifn.vkGetPhysicalDeviceSurfacePresentModesKHR( + physical_device, surface, &present_mode_count, + present_modes_were_empty ? nullptr : present_modes.data()); + // If the original presentation mode count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (present_modes_get_result == VK_SUCCESS || + present_modes_get_result == VK_INCOMPLETE) { + present_modes.resize(present_mode_count); + if (present_modes_get_result == VK_SUCCESS && + (!present_modes_were_empty || !present_mode_count)) { + break; + } + } else { + break; + } + } + if (present_modes_get_result != VK_SUCCESS) { + // Assuming FIFO only (required everywhere) in case of an error. + present_modes.clear(); + } + + // Create the swapchain. + VkSwapchainCreateInfoKHR swapchain_create_info; + swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_create_info.pNext = nullptr; + swapchain_create_info.flags = 0; + swapchain_create_info.surface = surface; + swapchain_create_info.minImageCount = + std::max(kSubmissionCount, surface_capabilities.minImageCount); + if (surface_capabilities.maxImageCount) { + swapchain_create_info.minImageCount = + std::min(swapchain_create_info.minImageCount, + surface_capabilities.maxImageCount); + } + swapchain_create_info.imageFormat = image_format.format; + swapchain_create_info.imageColorSpace = image_format.colorSpace; + swapchain_create_info.imageExtent = image_extent; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + uint32_t swapchain_queue_family_indices[2]; + if (queue_family_index_graphics_compute != queue_family_index_present) { + // Using concurrent sharing mode to avoid an explicit ownership transfer + // before presenting, which would require an additional command buffer + // submission with the acquire barrier and a semaphore between the graphics + // queue and the present queue. Different queues are an extremely rare case, + // and Xenia only uses the swapchain for the final guest output and the + // internal UI, so keeping framebuffer compression is not worth the + // additional submission complexity and possibly latency. + swapchain_queue_family_indices[0] = queue_family_index_graphics_compute; + swapchain_queue_family_indices[1] = queue_family_index_present; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + swapchain_create_info.queueFamilyIndexCount = 2; + swapchain_create_info.pQueueFamilyIndices = swapchain_queue_family_indices; + } else { + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.queueFamilyIndexCount = 0; + swapchain_create_info.pQueueFamilyIndices = nullptr; + } + swapchain_create_info.preTransform = + (surface_capabilities.supportedTransforms & + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR + : VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; + // Prefer opaque to avoid blending in the window system, or let that be + // specified via the window system if it can't be forced. As a last resort, + // just pick any - guest output will write alpha of 1 anyway. + if (surface_capabilities.supportedCompositeAlpha & + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) { + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + } else if (surface_capabilities.supportedCompositeAlpha & + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) { + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; + } else { + uint32_t composite_alpha_shift; + if (!xe::bit_scan_forward( + uint32_t(surface_capabilities.supportedCompositeAlpha), + &composite_alpha_shift)) { + // Against the Vulkan specification, but breaks the logic here. + XELOGE( + "VulkanPresenter: The surface doesn't support any composite alpha " + "mode"); + return VK_NULL_HANDLE; + } + swapchain_create_info.compositeAlpha = + VkCompositeAlphaFlagBitsKHR(uint32_t(1) << composite_alpha_shift); + } + // As presentation is usually controlled by the GPU command processor, it's + // better to use modes that allow as quick acquisition as possible to avoid + // interfering with GPU command processing, and also to allow tearing so + // variable refresh rate may be used where it's available. + // Note: If the priorities here are changes, update the cvar descriptions. + if (cvars::vulkan_allow_present_mode_immediate && + std::find(present_modes.cbegin(), present_modes.cend(), + VK_PRESENT_MODE_IMMEDIATE_KHR) != present_modes.cend()) { + // Allowing tearing to reduce latency, and possibly variable refresh rate + // (though on Windows with borderless fullscreen, GDI copying is used + // instead of independent flip, so it's not supported there). + swapchain_create_info.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + } else if (cvars::vulkan_allow_present_mode_mailbox && + std::find(present_modes.cbegin(), present_modes.cend(), + VK_PRESENT_MODE_MAILBOX_KHR) != present_modes.cend()) { + // Allowing dropping frames to reduce latency, but no tearing. + swapchain_create_info.presentMode = VK_PRESENT_MODE_MAILBOX_KHR; + } else if (cvars::vulkan_allow_present_mode_fifo_relaxed && + std::find(present_modes.cbegin(), present_modes.cend(), + VK_PRESENT_MODE_FIFO_RELAXED_KHR) != + present_modes.cend()) { + // Limiting the frame rate, but lets too long frames cause tearing not to + // make the latency even worse. + swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; + } else { + // Highest latency (but always guaranteed to be available). + swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; + } + swapchain_create_info.clipped = VK_TRUE; + swapchain_create_info.oldSwapchain = old_swapchain; + VkSwapchainKHR swapchain; + if (dfn.vkCreateSwapchainKHR(device, &swapchain_create_info, nullptr, + &swapchain) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a swapchain"); + return VK_NULL_HANDLE; + } + XELOGVK( + "VulkanPresenter: Created {}x{} swapchain with format {}, color space " + "{}, presentation mode {}", + swapchain_create_info.imageExtent.width, + swapchain_create_info.imageExtent.height, + uint32_t(swapchain_create_info.imageFormat), + uint32_t(swapchain_create_info.imageColorSpace), + uint32_t(swapchain_create_info.presentMode)); + + present_queue_family_out = queue_family_index_present; + image_format_out = swapchain_create_info.imageFormat; + image_extent_out = swapchain_create_info.imageExtent; + is_fifo_out = + swapchain_create_info.presentMode == VK_PRESENT_MODE_FIFO_KHR || + swapchain_create_info.presentMode == VK_PRESENT_MODE_FIFO_RELAXED_KHR; + return swapchain; +} + +VkSwapchainKHR VulkanPresenter::PaintContext::PrepareForSwapchainRetirement() { + if (swapchain != VK_NULL_HANDLE) { + submission_tracker.AwaitAllSubmissionsCompletion(); + } + const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + for (const SwapchainFramebuffer& framebuffer : swapchain_framebuffers) { + dfn.vkDestroyFramebuffer(device, framebuffer.framebuffer, nullptr); + dfn.vkDestroyImageView(device, framebuffer.image_view, nullptr); + } + swapchain_framebuffers.clear(); + swapchain_images.clear(); + swapchain_extent.width = 0; + swapchain_extent.height = 0; + // The old swapchain must be destroyed externally. + VkSwapchainKHR old_swapchain = swapchain; + swapchain = nullptr; + return old_swapchain; +} + +void VulkanPresenter::PaintContext::DestroySwapchainAndVulkanSurface() { + VkSwapchainKHR old_swapchain = PrepareForSwapchainRetirement(); + if (old_swapchain != VK_NULL_HANDLE) { + const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + dfn.vkDestroySwapchainKHR(device, old_swapchain, nullptr); + } + present_queue_family = UINT32_MAX; + if (vulkan_surface != VK_NULL_HANDLE) { + const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); + VkInstance instance = provider.instance(); + ifn.vkDestroySurfaceKHR(instance, vulkan_surface, nullptr); + vulkan_surface = VK_NULL_HANDLE; + } +} + +VulkanPresenter::GuestOutputImage::~GuestOutputImage() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + if (view_ != VK_NULL_HANDLE) { + dfn.vkDestroyImageView(device, view_, nullptr); + } + if (image_ != VK_NULL_HANDLE) { + dfn.vkDestroyImage(device, image_, nullptr); + } + if (memory_ != VK_NULL_HANDLE) { + dfn.vkFreeMemory(device, memory_, nullptr); + } +} + +bool VulkanPresenter::GuestOutputImage::Initialize() { + VkImageCreateInfo image_create_info; + VkImageCreateInfo* image_create_info_last = &image_create_info; + image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_create_info.pNext = nullptr; + image_create_info.flags = 0; + image_create_info.imageType = VK_IMAGE_TYPE_2D; + image_create_info.format = kGuestOutputFormat; + image_create_info.extent.width = extent_.width; + image_create_info.extent.height = extent_.height; + image_create_info.extent.depth = 1; + image_create_info.mipLevels = 1; + image_create_info.arrayLayers = 1; + image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.queueFamilyIndexCount = 0; + image_create_info.pQueueFamilyIndices = nullptr; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if (!ui::vulkan::util::CreateDedicatedAllocationImage( + provider_, image_create_info, + ui::vulkan::util::MemoryPurpose::kDeviceLocal, image_, memory_)) { + XELOGE("VulkanPresenter: Failed to create a guest output image"); + return false; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkImageViewCreateInfo image_view_create_info; + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = nullptr; + image_view_create_info.flags = 0; + image_view_create_info.image = image_; + image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + image_view_create_info.format = kGuestOutputFormat; + image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.subresourceRange.aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT; + image_view_create_info.subresourceRange.baseMipLevel = 0; + image_view_create_info.subresourceRange.levelCount = 1; + image_view_create_info.subresourceRange.baseArrayLayer = 0; + image_view_create_info.subresourceRange.layerCount = 1; + if (dfn.vkCreateImageView(device, &image_view_create_info, nullptr, &view_) != + VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a guest output image view"); + return false; + } + + return true; +} + +Presenter::PaintResult VulkanPresenter::PaintAndPresentImpl( + bool execute_ui_drawers) { + // Begin the submission in place of the one not currently potentially used on + // the GPU. + uint64_t current_paint_submission_index = + paint_context_.submission_tracker.GetCurrentSubmission(); + uint64_t paint_submission_count = uint64_t(paint_context_.submissions.size()); + if (current_paint_submission_index >= paint_submission_count) { + paint_context_.submission_tracker.AwaitSubmissionCompletion( + current_paint_submission_index - paint_submission_count); + } + const PaintContext::Submission& paint_submission = + *paint_context_.submissions[current_paint_submission_index % + paint_submission_count]; + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkCommandPool draw_command_pool = paint_submission.draw_command_pool(); + if (dfn.vkResetCommandPool(device, draw_command_pool, 0) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to reset a command buffer for drawing to the " + "swapchain"); + return PaintResult::kNotPresented; + } + + VkCommandBuffer draw_command_buffer = paint_submission.draw_command_buffer(); + VkCommandBufferBeginInfo command_buffer_begin_info; + command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + command_buffer_begin_info.pNext = nullptr; + command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + command_buffer_begin_info.pInheritanceInfo = nullptr; + if (dfn.vkBeginCommandBuffer(draw_command_buffer, + &command_buffer_begin_info) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to being recording the command buffer for " + "drawing to the swapchain"); + return PaintResult::kNotPresented; + } + // vkResetCommandPool resets from both initial and recording states, still + // safe to return early from this function in case of an error. + + VkSemaphore acquire_semaphore = paint_submission.acquire_semaphore(); + uint32_t swapchain_image_index; + VkResult acquire_result = dfn.vkAcquireNextImageKHR( + device, paint_context_.swapchain, UINT64_MAX, acquire_semaphore, + VK_NULL_HANDLE, &swapchain_image_index); + switch (acquire_result) { + case VK_SUCCESS: + case VK_SUBOPTIMAL_KHR: + break; + case VK_ERROR_DEVICE_LOST: + XELOGE( + "VulkanPresenter: Failed to acquire the swapchain image as the " + "device has been lost"); + return PaintResult::kGpuLostResponsible; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_ERROR_SURFACE_LOST_KHR: + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: + // Not an error, reporting just as info (may normally occur while resizing + // on some platforms). + XELOGVK( + "VulkanPresenter: Presentation to the swapchain image has been " + "dropped as the swapchain or the surface has become outdated"); + return PaintResult::kNotPresentedConnectionOutdated; + default: + XELOGE("VulkanPresenter: Failed to acquire the swapchain image"); + return PaintResult::kNotPresented; + } + + // Non-zero extents needed for both the viewport (width must not be zero) and + // the guest output rectangle. + assert_not_zero(paint_context_.swapchain_extent.width); + assert_not_zero(paint_context_.swapchain_extent.height); + + bool swapchain_image_clear_needed = true; + VkClearAttachment swapchain_image_clear_attachment; + swapchain_image_clear_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + swapchain_image_clear_attachment.colorAttachment = 0; + swapchain_image_clear_attachment.clearValue.color.float32[0] = 0.0f; + swapchain_image_clear_attachment.clearValue.color.float32[1] = 0.0f; + swapchain_image_clear_attachment.clearValue.color.float32[2] = 0.0f; + swapchain_image_clear_attachment.clearValue.color.float32[3] = 1.0f; + + VkRenderPassBeginInfo swapchain_render_pass_begin_info; + swapchain_render_pass_begin_info.sType = + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + swapchain_render_pass_begin_info.pNext = nullptr; + swapchain_render_pass_begin_info.renderPass = + paint_context_.swapchain_render_pass; + swapchain_render_pass_begin_info.framebuffer = + paint_context_.swapchain_framebuffers[swapchain_image_index].framebuffer; + swapchain_render_pass_begin_info.renderArea.offset.x = 0; + swapchain_render_pass_begin_info.renderArea.offset.y = 0; + swapchain_render_pass_begin_info.renderArea.extent = + paint_context_.swapchain_extent; + swapchain_render_pass_begin_info.clearValueCount = 0; + swapchain_render_pass_begin_info.pClearValues = nullptr; + if (paint_context_.swapchain_render_pass_clear_load_op) { + swapchain_render_pass_begin_info.clearValueCount = 1; + swapchain_render_pass_begin_info.pClearValues = + &swapchain_image_clear_attachment.clearValue; + swapchain_image_clear_needed = false; + } + + bool swapchain_image_pass_begun = false; + + GuestOutputProperties guest_output_properties; + GuestOutputPaintConfig guest_output_paint_config; + std::shared_ptr guest_output_image; + { + uint32_t guest_output_mailbox_index; + std::unique_lock guest_output_consumer_lock( + ConsumeGuestOutput(guest_output_mailbox_index, &guest_output_properties, + &guest_output_paint_config)); + if (guest_output_mailbox_index != UINT32_MAX) { + assert_true(guest_output_images_[guest_output_mailbox_index] + .ever_successfully_refreshed); + guest_output_image = + guest_output_images_[guest_output_mailbox_index].image; + } + // Incremented the reference count of the guest output image - safe to leave + // the consumer critical section now as everything here either will be using + // the new reference or is exclusively owned by main target painting (and + // multiple threads can't paint the main target at the same time). + } + + if (guest_output_image) { + VkExtent2D max_framebuffer_extent = + util::GetMax2DFramebufferExtent(provider_); + GuestOutputPaintFlow guest_output_flow = GetGuestOutputPaintFlow( + guest_output_properties, paint_context_.swapchain_extent.width, + paint_context_.swapchain_extent.height, max_framebuffer_extent.width, + max_framebuffer_extent.height, guest_output_paint_config); + if (guest_output_flow.effect_count) { + // Store the main target reference to the guest output image so it's not + // destroyed while it's still potentially in use by main target painting + // queued on the GPU. + size_t guest_output_image_paint_ref_index = SIZE_MAX; + size_t guest_output_image_paint_ref_new_index = SIZE_MAX; + // Try to find the existing reference to the same image, or an already + // released (or a taken, but never actually used) slot. + for (size_t i = 0; + i < paint_context_.guest_output_image_paint_refs.size(); ++i) { + const std::pair>& + guest_output_image_paint_ref = + paint_context_.guest_output_image_paint_refs[i]; + if (guest_output_image_paint_ref.second == guest_output_image) { + guest_output_image_paint_ref_index = i; + break; + } + if (guest_output_image_paint_ref_new_index == SIZE_MAX && + (!guest_output_image_paint_ref.second || + !guest_output_image_paint_ref.first)) { + guest_output_image_paint_ref_new_index = i; + } + } + if (guest_output_image_paint_ref_index == SIZE_MAX) { + // New image - store the reference and create the descriptors. + if (guest_output_image_paint_ref_new_index == SIZE_MAX) { + // Replace the earliest used reference. + guest_output_image_paint_ref_new_index = 0; + for (size_t i = 1; + i < paint_context_.guest_output_image_paint_refs.size(); ++i) { + if (paint_context_.guest_output_image_paint_refs[i].first < + paint_context_ + .guest_output_image_paint_refs + [guest_output_image_paint_ref_new_index] + .first) { + guest_output_image_paint_ref_new_index = i; + } + } + // Await the completion of the usage of the old guest output image and + // its descriptors. + paint_context_.submission_tracker.AwaitSubmissionCompletion( + paint_context_ + .guest_output_image_paint_refs + [guest_output_image_paint_ref_new_index] + .first); + } + guest_output_image_paint_ref_index = + guest_output_image_paint_ref_new_index; + // The actual submission index will be set if the image is actually + // used, not dropped due to some error. + paint_context_ + .guest_output_image_paint_refs[guest_output_image_paint_ref_index] = + std::make_pair(uint64_t(0), guest_output_image); + // Create the descriptors of the new image. + VkDescriptorImageInfo guest_output_image_descriptor_image_info; + guest_output_image_descriptor_image_info.sampler = + provider_.GetHostSampler(VulkanProvider::HostSampler::kLinearClamp); + guest_output_image_descriptor_image_info.imageView = + guest_output_image->view(); + guest_output_image_descriptor_image_info.imageLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet guest_output_image_descriptor_write; + guest_output_image_descriptor_write.sType = + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + guest_output_image_descriptor_write.pNext = nullptr; + guest_output_image_descriptor_write.dstSet = + paint_context_.guest_output_descriptor_sets + [PaintContext::kGuestOutputDescriptorSetGuestOutput0Sampled + + guest_output_image_paint_ref_index]; + guest_output_image_descriptor_write.dstBinding = 0; + guest_output_image_descriptor_write.dstArrayElement = 0; + guest_output_image_descriptor_write.descriptorCount = 1; + guest_output_image_descriptor_write.descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + guest_output_image_descriptor_write.pImageInfo = + &guest_output_image_descriptor_image_info; + guest_output_image_descriptor_write.pBufferInfo = nullptr; + guest_output_image_descriptor_write.pTexelBufferView = nullptr; + dfn.vkUpdateDescriptorSets( + device, 1, &guest_output_image_descriptor_write, 0, nullptr); + } + + // Make sure intermediate textures of the needed size are available, and + // unneeded intermediate textures are destroyed. + for (size_t i = 0; i < kMaxGuestOutputPaintEffects - 1; ++i) { + std::pair intermediate_needed_size(0, 0); + if (i + 1 < guest_output_flow.effect_count) { + intermediate_needed_size = guest_output_flow.effect_output_sizes[i]; + } + std::unique_ptr& intermediate_image_ptr_ref = + paint_context_.guest_output_intermediate_images[i]; + VkExtent2D intermediate_current_extent( + intermediate_image_ptr_ref ? intermediate_image_ptr_ref->extent() + : VkExtent2D{}); + if (intermediate_current_extent.width != + intermediate_needed_size.first || + intermediate_current_extent.height != + intermediate_needed_size.second) { + if (intermediate_needed_size.first && + intermediate_needed_size.second) { + // Need to replace immediately as a new image with the requested + // size is needed. + if (intermediate_image_ptr_ref) { + paint_context_.submission_tracker.AwaitSubmissionCompletion( + paint_context_ + .guest_output_intermediate_image_last_submission); + intermediate_image_ptr_ref.reset(); + util::DestroyAndNullHandle( + dfn.vkDestroyFramebuffer, device, + paint_context_.guest_output_intermediate_framebuffers[i]); + } + // Image. + intermediate_image_ptr_ref = GuestOutputImage::Create( + provider_, intermediate_needed_size.first, + intermediate_needed_size.second); + if (!intermediate_image_ptr_ref) { + // Don't display the guest output, and don't try to create more + // intermediate textures (only destroy them). + guest_output_flow.effect_count = 0; + continue; + } + // Framebuffer. + VkImageView intermediate_framebuffer_attachment = + intermediate_image_ptr_ref->view(); + VkFramebufferCreateInfo intermediate_framebuffer_create_info; + intermediate_framebuffer_create_info.sType = + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + intermediate_framebuffer_create_info.pNext = nullptr; + intermediate_framebuffer_create_info.flags = 0; + intermediate_framebuffer_create_info.renderPass = + guest_output_intermediate_render_pass_; + intermediate_framebuffer_create_info.attachmentCount = 1; + intermediate_framebuffer_create_info.pAttachments = + &intermediate_framebuffer_attachment; + intermediate_framebuffer_create_info.width = + intermediate_needed_size.first; + intermediate_framebuffer_create_info.height = + intermediate_needed_size.second; + intermediate_framebuffer_create_info.layers = 1; + if (dfn.vkCreateFramebuffer( + device, &intermediate_framebuffer_create_info, nullptr, + &paint_context_ + .guest_output_intermediate_framebuffers[i]) != + VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a guest output " + "intermediate framebuffer"); + // Don't display the guest output, and don't try to create more + // intermediate textures (only destroy them). + guest_output_flow.effect_count = 0; + continue; + } + // Descriptors. + VkDescriptorImageInfo intermediate_descriptor_image_info; + intermediate_descriptor_image_info.sampler = + provider_.GetHostSampler( + VulkanProvider::HostSampler::kLinearClamp); + intermediate_descriptor_image_info.imageView = + intermediate_image_ptr_ref->view(); + intermediate_descriptor_image_info.imageLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet intermediate_descriptor_write; + intermediate_descriptor_write.sType = + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + intermediate_descriptor_write.pNext = nullptr; + intermediate_descriptor_write.dstSet = + paint_context_.guest_output_descriptor_sets + [PaintContext :: + kGuestOutputDescriptorSetIntermediate0Sampled + + i]; + intermediate_descriptor_write.dstBinding = 0; + intermediate_descriptor_write.dstArrayElement = 0; + intermediate_descriptor_write.descriptorCount = 1; + intermediate_descriptor_write.descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + intermediate_descriptor_write.pImageInfo = + &intermediate_descriptor_image_info; + intermediate_descriptor_write.pBufferInfo = nullptr; + intermediate_descriptor_write.pTexelBufferView = nullptr; + dfn.vkUpdateDescriptorSets( + device, 1, &intermediate_descriptor_write, 0, nullptr); + } else { + // Was previously needed, but not anymore - destroy when possible. + if (intermediate_image_ptr_ref && + paint_context_.submission_tracker + .UpdateAndGetCompletedSubmission() >= + paint_context_ + .guest_output_intermediate_image_last_submission) { + intermediate_image_ptr_ref.reset(); + util::DestroyAndNullHandle( + dfn.vkDestroyFramebuffer, device, + paint_context_.guest_output_intermediate_framebuffers[i]); + } + } + } + } + + if (guest_output_flow.effect_count) { + // Check if all the intermediate effects are supported by the + // implementation. + for (size_t i = 0; i + 1 < guest_output_flow.effect_count; ++i) { + if (paint_context_ + .guest_output_paint_pipelines[size_t( + guest_output_flow.effects[i])] + .intermediate_pipeline == VK_NULL_HANDLE) { + guest_output_flow.effect_count = 0; + break; + } + } + // Ensure the pipeline exists for the final effect drawing to the + // swapchain, for the render pass with the up-to-date image format. + GuestOutputPaintEffect swapchain_effect = + guest_output_flow.effects[guest_output_flow.effect_count - 1]; + PaintContext::GuestOutputPaintPipeline& swapchain_effect_pipeline = + paint_context_ + .guest_output_paint_pipelines[size_t(swapchain_effect)]; + if (swapchain_effect_pipeline.swapchain_pipeline != VK_NULL_HANDLE && + swapchain_effect_pipeline.swapchain_format != + paint_context_.swapchain_render_pass_format) { + paint_context_.submission_tracker.AwaitSubmissionCompletion( + paint_context_.guest_output_image_paint_last_submission); + util::DestroyAndNullHandle( + dfn.vkDestroyPipeline, device, + swapchain_effect_pipeline.swapchain_pipeline); + } + if (swapchain_effect_pipeline.swapchain_pipeline == VK_NULL_HANDLE) { + assert_true(CanGuestOutputPaintEffectBeFinal(swapchain_effect)); + assert_true(guest_output_paint_fs_[size_t(swapchain_effect)] != + VK_NULL_HANDLE); + swapchain_effect_pipeline.swapchain_pipeline = + CreateGuestOutputPaintPipeline( + swapchain_effect, paint_context_.swapchain_render_pass); + if (swapchain_effect_pipeline.swapchain_pipeline == VK_NULL_HANDLE) { + guest_output_flow.effect_count = 0; + } + } + } + + if (guest_output_flow.effect_count) { + // Actually draw the guest output. + paint_context_ + .guest_output_image_paint_refs[guest_output_image_paint_ref_index] + .first = current_paint_submission_index; + paint_context_.guest_output_image_paint_last_submission = + current_paint_submission_index; + VkViewport guest_output_viewport; + guest_output_viewport.x = 0.0f; + guest_output_viewport.y = 0.0f; + guest_output_viewport.minDepth = 0.0f; + guest_output_viewport.maxDepth = 1.0f; + VkRect2D guest_output_scissor; + guest_output_scissor.offset.x = 0; + guest_output_scissor.offset.y = 0; + if (guest_output_flow.effect_count > 1) { + paint_context_.guest_output_intermediate_image_last_submission = + current_paint_submission_index; + } + for (size_t i = 0; i < guest_output_flow.effect_count; ++i) { + bool is_final_effect = i + 1 >= guest_output_flow.effect_count; + + int32_t effect_rect_x, effect_rect_y; + std::pair effect_rect_size = + guest_output_flow.effect_output_sizes[i]; + if (is_final_effect) { + effect_rect_x = guest_output_flow.output_x; + effect_rect_y = guest_output_flow.output_y; + dfn.vkCmdBeginRenderPass(draw_command_buffer, + &swapchain_render_pass_begin_info, + VK_SUBPASS_CONTENTS_INLINE); + swapchain_image_pass_begun = true; + guest_output_viewport.width = + float(paint_context_.swapchain_extent.width); + guest_output_viewport.height = + float(paint_context_.swapchain_extent.height); + guest_output_scissor.extent.width = + paint_context_.swapchain_extent.width; + guest_output_scissor.extent.height = + paint_context_.swapchain_extent.height; + } else { + effect_rect_x = 0; + effect_rect_y = 0; + VkRenderPassBeginInfo intermediate_render_pass_begin_info; + intermediate_render_pass_begin_info.sType = + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + intermediate_render_pass_begin_info.pNext = nullptr; + intermediate_render_pass_begin_info.renderPass = + guest_output_intermediate_render_pass_; + intermediate_render_pass_begin_info.framebuffer = + paint_context_.guest_output_intermediate_framebuffers[i]; + intermediate_render_pass_begin_info.renderArea.offset.x = 0; + intermediate_render_pass_begin_info.renderArea.offset.y = 0; + intermediate_render_pass_begin_info.renderArea.extent.width = + effect_rect_size.first; + intermediate_render_pass_begin_info.renderArea.extent.height = + effect_rect_size.second; + intermediate_render_pass_begin_info.clearValueCount = 0; + intermediate_render_pass_begin_info.pClearValues = nullptr; + dfn.vkCmdBeginRenderPass(draw_command_buffer, + &intermediate_render_pass_begin_info, + VK_SUBPASS_CONTENTS_INLINE); + guest_output_viewport.width = float(effect_rect_size.first); + guest_output_viewport.height = float(effect_rect_size.second); + guest_output_scissor.extent.width = effect_rect_size.first; + guest_output_scissor.extent.height = effect_rect_size.second; + } + dfn.vkCmdSetViewport(draw_command_buffer, 0, 1, + &guest_output_viewport); + dfn.vkCmdSetScissor(draw_command_buffer, 0, 1, &guest_output_scissor); + + GuestOutputPaintEffect effect = guest_output_flow.effects[i]; + + const PaintContext::GuestOutputPaintPipeline& effect_pipeline = + paint_context_.guest_output_paint_pipelines[size_t(effect)]; + VkPipeline effect_vulkan_pipeline = + is_final_effect ? effect_pipeline.swapchain_pipeline + : effect_pipeline.intermediate_pipeline; + assert_true(effect_vulkan_pipeline != VK_NULL_HANDLE); + dfn.vkCmdBindPipeline(draw_command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + effect_vulkan_pipeline); + + GuestOutputPaintPipelineLayoutIndex + guest_output_paint_pipeline_layout_index = + GetGuestOutputPaintPipelineLayoutIndex(effect); + VkPipelineLayout guest_output_paint_pipeline_layout = + guest_output_paint_pipeline_layouts_ + [guest_output_paint_pipeline_layout_index]; + + PaintContext::GuestOutputDescriptorSet effect_src_descriptor_set; + if (i) { + effect_src_descriptor_set = PaintContext::GuestOutputDescriptorSet( + PaintContext::kGuestOutputDescriptorSetIntermediate0Sampled + + (i - 1)); + } else { + effect_src_descriptor_set = PaintContext::GuestOutputDescriptorSet( + PaintContext::kGuestOutputDescriptorSetGuestOutput0Sampled + + guest_output_image_paint_ref_index); + } + dfn.vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + guest_output_paint_pipeline_layout, 0, 1, + &paint_context_ + .guest_output_descriptor_sets[effect_src_descriptor_set], + 0, nullptr); + + GuestOutputPaintRectangleConstants effect_rect_constants; + float effect_x_to_ndc = 2.0f / guest_output_viewport.width; + float effect_y_to_ndc = 2.0f / guest_output_viewport.height; + effect_rect_constants.x = + -1.0f + float(effect_rect_x) * effect_x_to_ndc; + effect_rect_constants.y = + -1.0f + float(effect_rect_y) * effect_y_to_ndc; + effect_rect_constants.width = + float(effect_rect_size.first) * effect_x_to_ndc; + effect_rect_constants.height = + float(effect_rect_size.second) * effect_y_to_ndc; + dfn.vkCmdPushConstants( + draw_command_buffer, guest_output_paint_pipeline_layout, + VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(effect_rect_constants), + &effect_rect_constants); + + uint32_t effect_constants_size = 0; + union { + BilinearConstants bilinear; + CasSharpenConstants cas_sharpen; + CasResampleConstants cas_resample; + FsrEasuConstants fsr_easu; + FsrRcasConstants fsr_rcas; + } effect_constants; + switch (guest_output_paint_pipeline_layout_index) { + case kGuestOutputPaintPipelineLayoutIndexBilinear: { + effect_constants_size = sizeof(effect_constants.bilinear); + effect_constants.bilinear.Initialize(guest_output_flow, i); + } break; + case kGuestOutputPaintPipelineLayoutIndexCasSharpen: { + effect_constants_size = sizeof(effect_constants.cas_sharpen); + effect_constants.cas_sharpen.Initialize( + guest_output_flow, i, guest_output_paint_config); + } break; + case kGuestOutputPaintPipelineLayoutIndexCasResample: { + effect_constants_size = sizeof(effect_constants.cas_resample); + effect_constants.cas_resample.Initialize( + guest_output_flow, i, guest_output_paint_config); + } break; + case kGuestOutputPaintPipelineLayoutIndexFsrEasu: { + effect_constants_size = sizeof(effect_constants.fsr_easu); + effect_constants.fsr_easu.Initialize(guest_output_flow, i); + } break; + case kGuestOutputPaintPipelineLayoutIndexFsrRcas: { + effect_constants_size = sizeof(effect_constants.fsr_rcas); + effect_constants.fsr_rcas.Initialize(guest_output_flow, i, + guest_output_paint_config); + } break; + default: + break; + } + if (effect_constants_size) { + dfn.vkCmdPushConstants( + draw_command_buffer, guest_output_paint_pipeline_layout, + VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(effect_rect_constants), + effect_constants_size, &effect_constants); + } + + dfn.vkCmdDraw(draw_command_buffer, 4, 1, 0, 0); + + if (is_final_effect) { + // Clear the letterbox around the guest output if the guest output + // doesn't cover the entire swapchain image. + if (swapchain_image_clear_needed && + guest_output_flow.letterbox_clear_rectangle_count) { + VkClearRect letterbox_clear_vulkan_rectangles + [GuestOutputPaintFlow::kMaxClearRectangles]; + for (size_t i = 0; + i < guest_output_flow.letterbox_clear_rectangle_count; ++i) { + VkClearRect& letterbox_clear_vulkan_rectangle = + letterbox_clear_vulkan_rectangles[i]; + const GuestOutputPaintFlow::ClearRectangle& + letterbox_clear_rectangle = + guest_output_flow.letterbox_clear_rectangles[i]; + letterbox_clear_vulkan_rectangle.rect.offset.x = + int32_t(letterbox_clear_rectangle.x); + letterbox_clear_vulkan_rectangle.rect.offset.y = + int32_t(letterbox_clear_rectangle.y); + letterbox_clear_vulkan_rectangle.rect.extent.width = + letterbox_clear_rectangle.width; + letterbox_clear_vulkan_rectangle.rect.extent.height = + letterbox_clear_rectangle.height; + letterbox_clear_vulkan_rectangle.baseArrayLayer = 0; + letterbox_clear_vulkan_rectangle.layerCount = 1; + } + dfn.vkCmdClearAttachments( + draw_command_buffer, 1, &swapchain_image_clear_attachment, + uint32_t(guest_output_flow.letterbox_clear_rectangle_count), + letterbox_clear_vulkan_rectangles); + } + swapchain_image_clear_needed = false; + } else { + // Still need the swapchain pass to be open for UI drawing. + dfn.vkCmdEndRenderPass(draw_command_buffer); + } + } + } + } + } + + // Release main target guest output image references that aren't needed + // anymore (this is done after various potential guest-output-related main + // target submission tracker waits so the completed submission value is the + // most actual). + uint64_t completed_paint_submission = + paint_context_.submission_tracker.UpdateAndGetCompletedSubmission(); + for (std::pair>& + guest_output_image_paint_ref : + paint_context_.guest_output_image_paint_refs) { + if (!guest_output_image_paint_ref.second || + guest_output_image_paint_ref.second == guest_output_image) { + continue; + } + if (completed_paint_submission >= guest_output_image_paint_ref.first) { + guest_output_image_paint_ref.second.reset(); + } + } + + // If hasn't presented the guest output, begin the pass to clear and, if + // needed, to draw the UI. + if (!swapchain_image_pass_begun) { + dfn.vkCmdBeginRenderPass(draw_command_buffer, + &swapchain_render_pass_begin_info, + VK_SUBPASS_CONTENTS_INLINE); + } + if (swapchain_image_clear_needed) { + VkClearRect swapchain_image_clear_rectangle; + swapchain_image_clear_rectangle.rect.offset.x = 0; + swapchain_image_clear_rectangle.rect.offset.y = 0; + swapchain_image_clear_rectangle.rect.extent = + paint_context_.swapchain_extent; + swapchain_image_clear_rectangle.baseArrayLayer = 0; + swapchain_image_clear_rectangle.layerCount = 1; + dfn.vkCmdClearAttachments(draw_command_buffer, 1, + &swapchain_image_clear_attachment, 1, + &swapchain_image_clear_rectangle); + swapchain_image_clear_needed = false; + } + + if (execute_ui_drawers) { + // Draw the UI. + VulkanUIDrawContext ui_draw_context( + *this, paint_context_.swapchain_extent.width, + paint_context_.swapchain_extent.height, draw_command_buffer, + ui_submission_tracker_.GetCurrentSubmission(), + ui_submission_tracker_.UpdateAndGetCompletedSubmission(), + paint_context_.swapchain_render_pass, + paint_context_.swapchain_render_pass_format); + ExecuteUIDrawersFromUIThread(ui_draw_context); + } + + dfn.vkCmdEndRenderPass(draw_command_buffer); + + dfn.vkEndCommandBuffer(draw_command_buffer); + + VkPipelineStageFlags acquire_semaphore_wait_stage = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkCommandBuffer command_buffers[2]; + uint32_t command_buffer_count = 0; + // UI setup command buffers must be accessed only if execute_ui_drawers is not + // null, to identify the UI thread. + size_t ui_setup_command_buffer_index = + execute_ui_drawers ? paint_context_.ui_setup_command_buffer_current_index + : SIZE_MAX; + if (ui_setup_command_buffer_index != SIZE_MAX) { + PaintContext::UISetupCommandBuffer& ui_setup_command_buffer = + paint_context_.ui_setup_command_buffers[ui_setup_command_buffer_index]; + dfn.vkEndCommandBuffer(ui_setup_command_buffer.command_buffer); + command_buffers[command_buffer_count++] = + ui_setup_command_buffer.command_buffer; + // Release the current UI setup command buffer regardless of submission + // result. Failed submissions (if the UI submission index wasn't incremented + // since the previous draw) should be handled by UI drawers themselves by + // retrying all the failed work if needed. + paint_context_.ui_setup_command_buffer_current_index = SIZE_MAX; + } + command_buffers[command_buffer_count++] = draw_command_buffer; + VkSemaphore present_semaphore = paint_submission.present_semaphore(); + VkSubmitInfo submit_info; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = &acquire_semaphore; + submit_info.pWaitDstStageMask = &acquire_semaphore_wait_stage; + submit_info.commandBufferCount = command_buffer_count; + submit_info.pCommandBuffers = command_buffers; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &present_semaphore; + { + VulkanSubmissionTracker::FenceAcquisition fence_acqusition( + paint_context_.submission_tracker.AcquireFenceToAdvanceSubmission()); + // Also update the submission tracker giving submission indices to UI draw + // callbacks if submission is successful. + VulkanSubmissionTracker::FenceAcquisition ui_fence_acquisition; + if (execute_ui_drawers) { + ui_fence_acquisition = + ui_submission_tracker_.AcquireFenceToAdvanceSubmission(); + } + VkResult submit_result; + { + VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(provider_.queue_family_graphics_compute(), 0)); + submit_result = dfn.vkQueueSubmit(queue_acquisition.queue, 1, + &submit_info, fence_acqusition.fence()); + if (ui_fence_acquisition.fence() != VK_NULL_HANDLE && + submit_result == VK_SUCCESS) { + if (dfn.vkQueueSubmit(queue_acquisition.queue, 0, nullptr, + ui_fence_acquisition.fence()) != VK_SUCCESS) { + ui_fence_acquisition.SubmissionSucceededSignalFailed(); + } + } + } + if (submit_result != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to submit command buffers"); + fence_acqusition.SubmissionFailedOrDropped(); + ui_fence_acquisition.SubmissionFailedOrDropped(); + if (ui_setup_command_buffer_index != SIZE_MAX) { + // If failed to submit, make the UI setup command buffer available for + // immediate reuse, as the completed submission index won't be updated + // to the current index, and failing submissions with setup command + // buffer over and over will result in never reusing the setup command + // buffers. + paint_context_.ui_setup_command_buffers[ui_setup_command_buffer_index] + .last_usage_submission_index = 0; + } + // The image is in an acquired state - but now, it will be in it forever. + // To avoid that, recreate the swapchain - don't return just + // kNotPresented. + return PaintResult::kNotPresentedConnectionOutdated; + } + } + + VkPresentInfoKHR present_info; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_info.pNext = nullptr; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = &present_semaphore; + present_info.swapchainCount = 1; + present_info.pSwapchains = &paint_context_.swapchain; + present_info.pImageIndices = &swapchain_image_index; + present_info.pResults = nullptr; + VkResult present_result; + { + VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(paint_context_.present_queue_family, 0)); + present_result = + dfn.vkQueuePresentKHR(queue_acquisition.queue, &present_info); + } + switch (present_result) { + case VK_SUCCESS: + return PaintResult::kPresented; + case VK_SUBOPTIMAL_KHR: + return PaintResult::kPresentedSuboptimal; + case VK_ERROR_DEVICE_LOST: + XELOGE( + "VulkanPresenter: Failed to present the swapchain image as the " + "device has been lost"); + return PaintResult::kGpuLostResponsible; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_ERROR_SURFACE_LOST_KHR: + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: + // Not an error, reporting just as info (may normally occur while resizing + // on some platforms). + XELOGVK( + "VulkanPresenter: Presentation to the swapchain image has been " + "dropped as the swapchain or the surface has become outdated"); + // Note that the semaphore wait (followed by reset) has been enqueued, + // however, this should have no effect on anything here likely. + return PaintResult::kNotPresentedConnectionOutdated; + default: + XELOGE("VulkanPresenter: Failed to present the swapchain image"); + // The image is in an acquired state - but now, it will be in it forever. + // To avoid that, recreate the swapchain - don't return just + // kNotPresented. + return PaintResult::kNotPresentedConnectionOutdated; + } +} + +bool VulkanPresenter::InitializeSurfaceIndependent() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkSampler sampler_linear_clamp = + provider_.GetHostSampler(VulkanProvider::HostSampler::kLinearClamp); + VkDescriptorSetLayoutBinding guest_output_image_binding; + guest_output_image_binding.binding = 0; + guest_output_image_binding.descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + guest_output_image_binding.descriptorCount = 1; + guest_output_image_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + guest_output_image_binding.pImmutableSamplers = &sampler_linear_clamp; + VkDescriptorSetLayoutCreateInfo + guest_output_paint_image_descriptor_set_layout_create_info; + guest_output_paint_image_descriptor_set_layout_create_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + guest_output_paint_image_descriptor_set_layout_create_info.pNext = nullptr; + guest_output_paint_image_descriptor_set_layout_create_info.flags = 0; + guest_output_paint_image_descriptor_set_layout_create_info.bindingCount = 1; + guest_output_paint_image_descriptor_set_layout_create_info.pBindings = + &guest_output_image_binding; + if (dfn.vkCreateDescriptorSetLayout( + device, &guest_output_paint_image_descriptor_set_layout_create_info, + nullptr, + &guest_output_paint_image_descriptor_set_layout_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output image descriptor " + "set layout"); + return false; + } + + VkPushConstantRange guest_output_paint_push_constant_ranges[2]; + VkPushConstantRange& guest_output_paint_push_constant_range_rect = + guest_output_paint_push_constant_ranges[0]; + guest_output_paint_push_constant_range_rect.stageFlags = + VK_SHADER_STAGE_VERTEX_BIT; + guest_output_paint_push_constant_range_rect.offset = 0; + guest_output_paint_push_constant_range_rect.size = + sizeof(GuestOutputPaintRectangleConstants); + VkPushConstantRange& guest_output_paint_push_constant_range_ffx = + guest_output_paint_push_constant_ranges[1]; + guest_output_paint_push_constant_range_ffx.stageFlags = + VK_SHADER_STAGE_FRAGMENT_BIT; + guest_output_paint_push_constant_range_ffx.offset = + guest_output_paint_push_constant_ranges[0].offset + + guest_output_paint_push_constant_ranges[0].size; + VkPipelineLayoutCreateInfo guest_output_paint_pipeline_layout_create_info; + guest_output_paint_pipeline_layout_create_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + guest_output_paint_pipeline_layout_create_info.pNext = nullptr; + guest_output_paint_pipeline_layout_create_info.flags = 0; + guest_output_paint_pipeline_layout_create_info.setLayoutCount = 1; + guest_output_paint_pipeline_layout_create_info.pSetLayouts = + &guest_output_paint_image_descriptor_set_layout_; + guest_output_paint_pipeline_layout_create_info.pPushConstantRanges = + guest_output_paint_push_constant_ranges; + for (size_t i = 0; i < size_t(kGuestOutputPaintPipelineLayoutCount); ++i) { + switch (GuestOutputPaintPipelineLayoutIndex(i)) { + case kGuestOutputPaintPipelineLayoutIndexBilinear: + guest_output_paint_push_constant_range_ffx.size = + sizeof(BilinearConstants); + break; + case kGuestOutputPaintPipelineLayoutIndexCasSharpen: + guest_output_paint_push_constant_range_ffx.size = + sizeof(CasSharpenConstants); + break; + case kGuestOutputPaintPipelineLayoutIndexCasResample: + guest_output_paint_push_constant_range_ffx.size = + sizeof(CasResampleConstants); + break; + case kGuestOutputPaintPipelineLayoutIndexFsrEasu: + guest_output_paint_push_constant_range_ffx.size = + sizeof(FsrEasuConstants); + break; + case kGuestOutputPaintPipelineLayoutIndexFsrRcas: + guest_output_paint_push_constant_range_ffx.size = + sizeof(FsrRcasConstants); + break; + default: + assert_unhandled_case(GuestOutputPaintPipelineLayoutIndex(i)); + continue; + } + guest_output_paint_pipeline_layout_create_info.pushConstantRangeCount = + 1 + uint32_t(guest_output_paint_push_constant_range_ffx.size != 0); + if (dfn.vkCreatePipelineLayout( + device, &guest_output_paint_pipeline_layout_create_info, nullptr, + &guest_output_paint_pipeline_layouts_[i]) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a guest output presentation " + "pipeline layout with {} bytes of push constants", + guest_output_paint_push_constant_range_rect.size + + guest_output_paint_push_constant_range_ffx.size); + return false; + } + } + + VkShaderModuleCreateInfo shader_module_create_info; + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_create_info.pNext = nullptr; + shader_module_create_info.flags = 0; + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_triangle_strip_rect_vert); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_triangle_strip_rect_vert); + if (dfn.vkCreateShaderModule(device, &shader_module_create_info, nullptr, + &guest_output_paint_vs_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output presentation " + "vertex shader module"); + return false; + } + for (size_t i = 0; i < size_t(GuestOutputPaintEffect::kCount); ++i) { + GuestOutputPaintEffect guest_output_paint_effect = + GuestOutputPaintEffect(i); + switch (guest_output_paint_effect) { + case GuestOutputPaintEffect::kBilinear: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_bilinear_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_bilinear_frag); + break; + case GuestOutputPaintEffect::kBilinearDither: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_bilinear_dither_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_bilinear_dither_frag); + break; + case GuestOutputPaintEffect::kCasSharpen: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_cas_sharpen_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_cas_sharpen_frag); + break; + case GuestOutputPaintEffect::kCasSharpenDither: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_cas_sharpen_dither_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_cas_sharpen_dither_frag); + break; + case GuestOutputPaintEffect::kCasResample: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_cas_resample_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_cas_resample_frag); + break; + case GuestOutputPaintEffect::kCasResampleDither: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_cas_resample_dither_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_cas_resample_dither_frag); + break; + case GuestOutputPaintEffect::kFsrEasu: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_fsr_easu_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_fsr_easu_frag); + break; + case GuestOutputPaintEffect::kFsrRcas: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_fsr_rcas_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_fsr_rcas_frag); + break; + case GuestOutputPaintEffect::kFsrRcasDither: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_fsr_rcas_dither_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_fsr_rcas_dither_frag); + break; + default: + // Not supported by this implementation. + continue; + } + if (dfn.vkCreateShaderModule(device, &shader_module_create_info, nullptr, + &guest_output_paint_fs_[i]) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output painting shader " + "module for effect {}", + i); + return false; + } + } + + VkAttachmentDescription intermediate_render_pass_attachment; + intermediate_render_pass_attachment.flags = 0; + intermediate_render_pass_attachment.format = kGuestOutputFormat; + intermediate_render_pass_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + intermediate_render_pass_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + intermediate_render_pass_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + intermediate_render_pass_attachment.stencilLoadOp = + VK_ATTACHMENT_LOAD_OP_DONT_CARE; + intermediate_render_pass_attachment.stencilStoreOp = + VK_ATTACHMENT_STORE_OP_DONT_CARE; + intermediate_render_pass_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + intermediate_render_pass_attachment.finalLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkAttachmentReference intermediate_render_pass_color_attachment; + intermediate_render_pass_color_attachment.attachment = 0; + intermediate_render_pass_color_attachment.layout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkSubpassDescription intermediate_render_pass_subpass = {}; + intermediate_render_pass_subpass.pipelineBindPoint = + VK_PIPELINE_BIND_POINT_GRAPHICS; + intermediate_render_pass_subpass.colorAttachmentCount = 1; + intermediate_render_pass_subpass.pColorAttachments = + &intermediate_render_pass_color_attachment; + VkSubpassDependency intermediate_render_pass_dependencies[2]; + intermediate_render_pass_dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + intermediate_render_pass_dependencies[0].dstSubpass = 0; + intermediate_render_pass_dependencies[0].srcStageMask = + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + intermediate_render_pass_dependencies[0].dstStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + intermediate_render_pass_dependencies[0].srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; + intermediate_render_pass_dependencies[0].dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + intermediate_render_pass_dependencies[0].dependencyFlags = 0; + intermediate_render_pass_dependencies[1].srcSubpass = 0; + intermediate_render_pass_dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + intermediate_render_pass_dependencies[1].srcStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + intermediate_render_pass_dependencies[1].dstStageMask = + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + intermediate_render_pass_dependencies[1].srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + intermediate_render_pass_dependencies[1].dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; + intermediate_render_pass_dependencies[1].dependencyFlags = 0; + VkRenderPassCreateInfo intermediate_render_pass_create_info; + intermediate_render_pass_create_info.sType = + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + intermediate_render_pass_create_info.pNext = nullptr; + intermediate_render_pass_create_info.flags = 0; + intermediate_render_pass_create_info.attachmentCount = 1; + intermediate_render_pass_create_info.pAttachments = + &intermediate_render_pass_attachment; + intermediate_render_pass_create_info.subpassCount = 1; + intermediate_render_pass_create_info.pSubpasses = + &intermediate_render_pass_subpass; + intermediate_render_pass_create_info.dependencyCount = + uint32_t(xe::countof(intermediate_render_pass_dependencies)); + intermediate_render_pass_create_info.pDependencies = + intermediate_render_pass_dependencies; + if (dfn.vkCreateRenderPass( + device, &intermediate_render_pass_create_info, nullptr, + &guest_output_intermediate_render_pass_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output intermediate image " + "render pass"); + return false; + } + + // Initialize connection-independent parts of the painting context. + + for (size_t i = 0; i < paint_context_.submissions.size(); ++i) { + paint_context_.submissions[i] = PaintContext::Submission::Create(provider_); + if (!paint_context_.submissions[i]) { + return false; + } + } + + // Guest output paint pipelines drawing to intermediate images, not depending + // on runtime state unlike ones drawing to the swapchain images as those + // depend on the swapchain format. + for (size_t i = 0; i < size_t(GuestOutputPaintEffect::kCount); ++i) { + if (!CanGuestOutputPaintEffectBeIntermediate(GuestOutputPaintEffect(i)) || + guest_output_paint_fs_[i] == VK_NULL_HANDLE) { + continue; + } + VkPipeline guest_output_paint_intermediate_pipeline = + CreateGuestOutputPaintPipeline(GuestOutputPaintEffect(i), + guest_output_intermediate_render_pass_); + if (guest_output_paint_intermediate_pipeline == VK_NULL_HANDLE) { + return false; + } + paint_context_.guest_output_paint_pipelines[i].intermediate_pipeline = + guest_output_paint_intermediate_pipeline; + } + + // Guest output painting descriptor sets. + VkDescriptorPoolSize guest_output_paint_descriptor_pool_size; + guest_output_paint_descriptor_pool_size.type = + guest_output_image_binding.descriptorType; + // Each descriptor set contains only 1 descriptor. + guest_output_paint_descriptor_pool_size.descriptorCount = + PaintContext::kGuestOutputDescriptorSetCount; + VkDescriptorPoolCreateInfo guest_output_paint_descriptor_pool_create_info; + guest_output_paint_descriptor_pool_create_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + guest_output_paint_descriptor_pool_create_info.pNext = nullptr; + guest_output_paint_descriptor_pool_create_info.flags = 0; + guest_output_paint_descriptor_pool_create_info.maxSets = + PaintContext::kGuestOutputDescriptorSetCount; + guest_output_paint_descriptor_pool_create_info.poolSizeCount = 1; + guest_output_paint_descriptor_pool_create_info.pPoolSizes = + &guest_output_paint_descriptor_pool_size; + if (dfn.vkCreateDescriptorPool( + device, &guest_output_paint_descriptor_pool_create_info, nullptr, + &paint_context_.guest_output_descriptor_pool) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output painting " + "descriptor pool"); + return false; + } + VkDescriptorSetLayout guest_output_paint_descriptor_set_layouts + [PaintContext::kGuestOutputDescriptorSetCount]; + std::fill(guest_output_paint_descriptor_set_layouts, + guest_output_paint_descriptor_set_layouts + + xe::countof(guest_output_paint_descriptor_set_layouts), + guest_output_paint_image_descriptor_set_layout_); + VkDescriptorSetAllocateInfo guest_output_paint_descriptor_set_allocate_info; + guest_output_paint_descriptor_set_allocate_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + guest_output_paint_descriptor_set_allocate_info.pNext = nullptr; + guest_output_paint_descriptor_set_allocate_info.descriptorPool = + paint_context_.guest_output_descriptor_pool; + guest_output_paint_descriptor_set_allocate_info.descriptorSetCount = + PaintContext::kGuestOutputDescriptorSetCount; + guest_output_paint_descriptor_set_allocate_info.pSetLayouts = + guest_output_paint_descriptor_set_layouts; + if (dfn.vkAllocateDescriptorSets( + device, &guest_output_paint_descriptor_set_allocate_info, + paint_context_.guest_output_descriptor_sets) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to allocate the guest output painting " + "descriptor sets"); + return false; + } + + return InitializeCommonSurfaceIndependent(); +} + +VkPipeline VulkanPresenter::CreateGuestOutputPaintPipeline( + GuestOutputPaintEffect effect, VkRenderPass render_pass) { + VkPipelineShaderStageCreateInfo stages[2] = {}; + for (uint32_t i = 0; i < 2; ++i) { + VkPipelineShaderStageCreateInfo& stage = stages[i]; + stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage.stage = i ? VK_SHADER_STAGE_FRAGMENT_BIT : VK_SHADER_STAGE_VERTEX_BIT; + stage.pName = "main"; + } + stages[0].module = guest_output_paint_vs_; + stages[1].module = guest_output_paint_fs_[size_t(effect)]; + assert_true(stages[1].module != VK_NULL_HANDLE); + + VkPipelineVertexInputStateCreateInfo vertex_input_state = {}; + vertex_input_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state = {}; + input_assembly_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + + VkPipelineViewportStateCreateInfo viewport_state = {}; + viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_state.viewportCount = 1; + viewport_state.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo rasterization_state = {}; + rasterization_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; + rasterization_state.cullMode = VK_CULL_MODE_NONE; + rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterization_state.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo multisample_state = {}; + multisample_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state = {}; + color_blend_attachment_state.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + VkPipelineColorBlendStateCreateInfo color_blend_state = {}; + color_blend_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + color_blend_state.attachmentCount = 1; + color_blend_state.pAttachments = &color_blend_attachment_state; + + static const VkDynamicState kPipelineDynamicStates[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state.dynamicStateCount = + uint32_t(xe::countof(kPipelineDynamicStates)); + dynamic_state.pDynamicStates = kPipelineDynamicStates; + + VkGraphicsPipelineCreateInfo pipeline_create_info; + pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipeline_create_info.pNext = nullptr; + pipeline_create_info.flags = 0; + pipeline_create_info.stageCount = uint32_t(xe::countof(stages)); + pipeline_create_info.pStages = stages; + pipeline_create_info.pVertexInputState = &vertex_input_state; + pipeline_create_info.pInputAssemblyState = &input_assembly_state; + pipeline_create_info.pTessellationState = nullptr; + pipeline_create_info.pViewportState = &viewport_state; + pipeline_create_info.pRasterizationState = &rasterization_state; + pipeline_create_info.pMultisampleState = &multisample_state; + pipeline_create_info.pDepthStencilState = nullptr; + pipeline_create_info.pColorBlendState = &color_blend_state; + pipeline_create_info.pDynamicState = &dynamic_state; + pipeline_create_info.layout = guest_output_paint_pipeline_layouts_ + [GetGuestOutputPaintPipelineLayoutIndex(effect)]; + pipeline_create_info.renderPass = render_pass; + pipeline_create_info.subpass = 0; + pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_create_info.basePipelineIndex = UINT32_MAX; + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkPipeline pipeline; + if (dfn.vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, + &pipeline_create_info, nullptr, + &pipeline) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output painting pipeline " + "for effect {}", + size_t(effect)); + return VK_NULL_HANDLE; + } + return pipeline; +} + +} // namespace vulkan +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_presenter.h b/src/xenia/ui/vulkan/vulkan_presenter.h new file mode 100644 index 000000000..91e055c6d --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_presenter.h @@ -0,0 +1,518 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_VULKAN_VULKAN_PRESENTER_H_ +#define XENIA_UI_VULKAN_VULKAN_PRESENTER_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/platform.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/surface.h" +#include "xenia/ui/vulkan/vulkan_provider.h" +#include "xenia/ui/vulkan/vulkan_submission_tracker.h" + +namespace xe { +namespace ui { +namespace vulkan { + +class VulkanUIDrawContext final : public UIDrawContext { + public: + VulkanUIDrawContext(Presenter& presenter, uint32_t render_target_width, + uint32_t render_target_height, + VkCommandBuffer draw_command_buffer, + uint64_t submission_index_current, + uint64_t submission_index_completed, + VkRenderPass render_pass, VkFormat render_pass_format) + : UIDrawContext(presenter, render_target_width, render_target_height), + draw_command_buffer_(draw_command_buffer), + submission_index_current_(submission_index_current), + submission_index_completed_(submission_index_completed), + render_pass_(render_pass), + render_pass_format_(render_pass_format) {} + + VkCommandBuffer draw_command_buffer() const { return draw_command_buffer_; } + uint64_t submission_index_current() const { + return submission_index_current_; + } + uint64_t submission_index_completed() const { + return submission_index_completed_; + } + VkRenderPass render_pass() const { return render_pass_; } + VkFormat render_pass_format() const { return render_pass_format_; } + + private: + VkCommandBuffer draw_command_buffer_; + uint64_t submission_index_current_; + uint64_t submission_index_completed_; + // Has 1 subpass with a single render_pass_format_ attachment. + VkRenderPass render_pass_; + VkFormat render_pass_format_; +}; + +class VulkanPresenter final : public Presenter { + public: + // Maximum number of different guest output image versions still potentially + // considered alive that may be given to the refresher - this many instances + // of dependent objects (such as framebuffers) may need to be kept by the + // refresher across invocations (due to multiple-buffering of guest output + // images inside the presenter, different versions may be given even every + // invocation), to avoid recreation of dependent objects every frame. + static constexpr size_t kMaxActiveGuestOutputImageVersions = + kGuestOutputMailboxSize; + + static constexpr VkFormat kGuestOutputFormat = + VK_FORMAT_A2B10G10R10_UNORM_PACK32; + // The guest output is expected to be acquired and released in this state by + // the refresher. The exception is the first write to the current guest output + // image - in this case, a barrier is only needed from + // VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT without access. Also if the image is + // being refreshed for the first time, it's in VK_IMAGE_LAYOUT_UNDEFINED (but + // it's safe, and preferred, to transition it from VK_IMAGE_LAYOUT_UNDEFINED + // when writing to it in general). + static constexpr VkPipelineStageFlagBits kGuestOutputInternalStageMask = + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + static constexpr VkAccessFlags kGuestOutputInternalAccessMask = + VK_ACCESS_SHADER_READ_BIT; + static constexpr VkImageLayout kGuestOutputInternalLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + // The callback must use the graphics and compute queue 0 of the provider. + class VulkanGuestOutputRefreshContext final + : public GuestOutputRefreshContext { + public: + VulkanGuestOutputRefreshContext(bool& is_8bpc_out_ref, VkImage image, + VkImageView image_view, + uint64_t image_version, + bool image_ever_written_previously) + : GuestOutputRefreshContext(is_8bpc_out_ref), + image_(image), + image_view_(image_view), + image_version_(image_version), + image_ever_written_previously_(image_ever_written_previously) {} + + // The format is kGuestOutputFormat. + // Supports usage as a color attachment and as a sampled image, as well as + // transfer source (but the reason of that is guest output capturing). + VkImage image() const { return image_; } + VkImageView image_view() const { return image_view_; } + uint64_t image_version() const { return image_version_; } + // Whether a proper barrier must be done to acquire the image. + bool image_ever_written_previously() const { + return image_ever_written_previously_; + } + + private: + VkImage image_; + VkImageView image_view_; + uint64_t image_version_; + bool image_ever_written_previously_; + }; + + static std::unique_ptr Create( + HostGpuLossCallback host_gpu_loss_callback, VulkanProvider& provider) { + auto presenter = std::unique_ptr( + new VulkanPresenter(host_gpu_loss_callback, provider)); + if (!presenter->InitializeSurfaceIndependent()) { + return nullptr; + } + return presenter; + } + + ~VulkanPresenter(); + + VulkanProvider& provider() const { return provider_; } + + static Surface::TypeFlags GetSurfaceTypesSupportedByInstance( + const VulkanProvider::InstanceExtensions& instance_extensions) { + if (!instance_extensions.khr_surface) { + return 0; + } + Surface::TypeFlags type_flags = 0; +#if XE_PLATFORM_ANDROID + if (instance_extensions.khr_android_surface) { + type_flags |= Surface::kTypeFlag_AndroidNativeWindow; + } +#elif XE_PLATFORM_GNU_LINUX + if (instance_extensions.khr_xcb_surface) { + type_flags |= Surface::kTypeFlag_XcbWindow; + } +#elif XE_PLATFORM_WIN32 + if (instance_extensions.khr_win32_surface) { + type_flags |= Surface::kTypeFlag_Win32Hwnd; + } +#endif + return type_flags; + } + Surface::TypeFlags GetSupportedSurfaceTypes() const override; + + bool CaptureGuestOutput(RawImage& image_out) override; + + void AwaitUISubmissionCompletionFromUIThread(uint64_t submission_index) { + ui_submission_tracker_.AwaitSubmissionCompletion(submission_index); + } + VkCommandBuffer AcquireUISetupCommandBufferFromUIThread(); + + protected: + SurfacePaintConnectResult ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) override; + void DisconnectPaintingFromSurfaceFromUIThreadImpl() override; + + bool RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out_ref) override; + + PaintResult PaintAndPresentImpl(bool execute_ui_drawers) override; + + private: + // Usable for both the guest output image itself and for intermediate images. + class GuestOutputImage { + public: + static std::unique_ptr Create( + const VulkanProvider& provider, uint32_t width, uint32_t height) { + assert_not_zero(width); + assert_not_zero(height); + auto image = std::unique_ptr( + new GuestOutputImage(provider, width, height)); + if (!image->Initialize()) { + return nullptr; + } + return std::move(image); + } + + GuestOutputImage(const GuestOutputImage& image) = delete; + GuestOutputImage& operator=(const GuestOutputImage& image) = delete; + ~GuestOutputImage(); + + const VkExtent2D& extent() const { return extent_; } + + VkImage image() const { return image_; } + VkDeviceMemory memory() const { return memory_; } + VkImageView view() const { return view_; } + + private: + GuestOutputImage(const VulkanProvider& provider, uint32_t width, + uint32_t height) + : provider_(provider) { + extent_.width = width; + extent_.height = height; + } + + bool Initialize(); + + const VulkanProvider& provider_; + + VkExtent2D extent_; + VkImage image_ = VK_NULL_HANDLE; + VkDeviceMemory memory_ = VK_NULL_HANDLE; + VkImageView view_ = VK_NULL_HANDLE; + }; + + struct GuestOutputImageInstance { + // Refresher-side reference (painting has its own references for the purpose + // of destruction only after painting is done on the GPU). + std::shared_ptr image; + uint64_t version = UINT64_MAX; + uint64_t last_refresher_submission = 0; + // For choosing the barrier stage and access mask and layout depending on + // whether the image has previously been written. If an image is active + // after a refresh, it can be assumed that this is true. + bool ever_successfully_refreshed = false; + + void SetToNewImage(const std::shared_ptr& new_image, + uint64_t new_version) { + image = new_image; + version = new_version; + last_refresher_submission = 0; + ever_successfully_refreshed = false; + } + }; + + struct GuestOutputPaintRectangleConstants { + union { + struct { + float x; + float y; + }; + float offset[2]; + }; + union { + struct { + float width; + float height; + }; + float size[2]; + }; + }; + + enum GuestOutputPaintPipelineLayoutIndex : size_t { + kGuestOutputPaintPipelineLayoutIndexBilinear, + kGuestOutputPaintPipelineLayoutIndexCasSharpen, + kGuestOutputPaintPipelineLayoutIndexCasResample, + kGuestOutputPaintPipelineLayoutIndexFsrEasu, + kGuestOutputPaintPipelineLayoutIndexFsrRcas, + + kGuestOutputPaintPipelineLayoutCount, + }; + + static constexpr GuestOutputPaintPipelineLayoutIndex + GetGuestOutputPaintPipelineLayoutIndex(GuestOutputPaintEffect effect) { + switch (effect) { + case GuestOutputPaintEffect::kBilinear: + case GuestOutputPaintEffect::kBilinearDither: + return kGuestOutputPaintPipelineLayoutIndexBilinear; + case GuestOutputPaintEffect::kCasSharpen: + case GuestOutputPaintEffect::kCasSharpenDither: + return kGuestOutputPaintPipelineLayoutIndexCasSharpen; + case GuestOutputPaintEffect::kCasResample: + case GuestOutputPaintEffect::kCasResampleDither: + return kGuestOutputPaintPipelineLayoutIndexCasResample; + case GuestOutputPaintEffect::kFsrEasu: + return kGuestOutputPaintPipelineLayoutIndexFsrEasu; + case GuestOutputPaintEffect::kFsrRcas: + case GuestOutputPaintEffect::kFsrRcasDither: + return kGuestOutputPaintPipelineLayoutIndexFsrRcas; + default: + assert_unhandled_case(effect); + return kGuestOutputPaintPipelineLayoutCount; + } + } + + struct PaintContext { + class Submission { + public: + static std::unique_ptr Create( + const VulkanProvider& provider) { + auto submission = std::unique_ptr(new Submission(provider)); + if (!submission->Initialize()) { + return nullptr; + } + return submission; + } + + Submission(const Submission& submission) = delete; + Submission& operator=(const Submission& submission) = delete; + ~Submission(); + + VkSemaphore acquire_semaphore() const { return acquire_semaphore_; } + VkSemaphore present_semaphore() const { return present_semaphore_; } + VkCommandPool draw_command_pool() const { return draw_command_pool_; } + VkCommandBuffer draw_command_buffer() const { + return draw_command_buffer_; + } + + private: + explicit Submission(const VulkanProvider& provider) + : provider_(provider) {} + bool Initialize(); + + const VulkanProvider& provider_; + VkSemaphore acquire_semaphore_ = VK_NULL_HANDLE; + VkSemaphore present_semaphore_ = VK_NULL_HANDLE; + VkCommandPool draw_command_pool_ = VK_NULL_HANDLE; + VkCommandBuffer draw_command_buffer_ = VK_NULL_HANDLE; + }; + + static constexpr uint32_t kSubmissionCount = 3; + + struct GuestOutputPaintPipeline { + // Created on initialization. + VkPipeline intermediate_pipeline = VK_NULL_HANDLE; + // Created during guest output painting (after awaiting the last guest + // output paint if outdated and needs to be recreated), when needed, for + // the up-to-date render pass that draws to the swapchain with the actual + // image format. + VkPipeline swapchain_pipeline = VK_NULL_HANDLE; + VkFormat swapchain_format = VK_FORMAT_UNDEFINED; + }; + + enum GuestOutputDescriptorSet : uint32_t { + kGuestOutputDescriptorSetGuestOutput0Sampled, + + kGuestOutputDescriptorSetIntermediate0Sampled = + kGuestOutputDescriptorSetGuestOutput0Sampled + + kGuestOutputMailboxSize, + + kGuestOutputDescriptorSetCount = + kGuestOutputDescriptorSetIntermediate0Sampled + + kMaxGuestOutputPaintEffects - 1, + }; + + struct UISetupCommandBuffer { + UISetupCommandBuffer(VkCommandPool command_pool, + VkCommandBuffer command_buffer, + uint64_t last_usage_submission_index = 0) + : command_pool(command_pool), + command_buffer(command_buffer), + last_usage_submission_index(last_usage_submission_index) {} + + VkCommandPool command_pool; + VkCommandBuffer command_buffer; + uint64_t last_usage_submission_index; + }; + + struct SwapchainFramebuffer { + SwapchainFramebuffer(VkImageView image_view, VkFramebuffer framebuffer) + : image_view(image_view), framebuffer(framebuffer) {} + + VkImageView image_view; + VkFramebuffer framebuffer; + }; + + explicit PaintContext(VulkanProvider& provider) + : provider(provider), submission_tracker(provider) {} + PaintContext(const PaintContext& paint_context) = delete; + PaintContext& operator=(const PaintContext& paint_context) = delete; + + // The old swapchain, if passed, should be assumed to be retired after this + // call (though it may fail before the vkCreateSwapchainKHR that will + // technically retire it, so it will be in an undefined state), and needs to + // be destroyed externally no matter what the result is. + static VkSwapchainKHR CreateSwapchainForVulkanSurface( + const VulkanProvider& provider, VkSurfaceKHR surface, uint32_t width, + uint32_t height, VkSwapchainKHR old_swapchain, + uint32_t& present_queue_family_out, VkFormat& image_format_out, + VkExtent2D& image_extent_out, bool& is_fifo_out, + bool& ui_surface_unusable_out); + + // Destroys the swapchain and its derivatives, nulls `swapchain` and returns + // the original swapchain object, if it existed, for use as oldSwapchain if + // needed and for destruction. + VkSwapchainKHR PrepareForSwapchainRetirement(); + // May be called from the destructor of the presenter. + void DestroySwapchainAndVulkanSurface(); + + // Connection-indepedent. + + const VulkanProvider& provider; + + std::array, kSubmissionCount> + submissions; + VulkanSubmissionTracker submission_tracker; + + std::array + guest_output_paint_pipelines; + + VkDescriptorPool guest_output_descriptor_pool = VK_NULL_HANDLE; + // Descriptors are updated while painting if they're out of date. + VkDescriptorSet + guest_output_descriptor_sets[kGuestOutputDescriptorSetCount]; + + // Refreshed and cleaned up during guest output painting. The first is the + // paint submission index in which the guest output image (and its + // descriptors) was last used, the second is the reference to the image, + // which may be null. The indices are not mailbox indices here, rather, if + // the reference is not in this array yet, the most outdated reference, if + // needed, is replaced with the new one, awaiting the usage completion of + // the last paint usage. + std::array>, + kGuestOutputMailboxSize> + guest_output_image_paint_refs; + // The latest submission index at which any guest output image was drawn. + uint64_t guest_output_image_paint_last_submission = 0; + + // Current intermediate images for guest output painting, refreshed when + // painting guest output. + std::array, + kMaxGuestOutputPaintEffects - 1> + guest_output_intermediate_images; + // Created and destroyed alongside the images. UNORM only. + std::array + guest_output_intermediate_framebuffers = {}; + uint64_t guest_output_intermediate_image_last_submission = 0; + + // Command buffers optionally executed before the draw command buffer, + // outside the painting render pass. + std::vector ui_setup_command_buffers; + size_t ui_setup_command_buffer_current_index = SIZE_MAX; + + // Connection-specific. + + // May be reused between connections if the format stays the same. + VkRenderPass swapchain_render_pass = VK_NULL_HANDLE; + VkFormat swapchain_render_pass_format = VK_FORMAT_UNDEFINED; + bool swapchain_render_pass_clear_load_op = false; + + VkSurfaceKHR vulkan_surface = VK_NULL_HANDLE; + uint32_t present_queue_family = UINT32_MAX; + VkSwapchainKHR swapchain = VK_NULL_HANDLE; + VkExtent2D swapchain_extent = {}; + bool swapchain_is_fifo = false; + std::vector swapchain_images; + std::vector swapchain_framebuffers; + }; + + explicit VulkanPresenter(HostGpuLossCallback host_gpu_loss_callback, + VulkanProvider& provider) + : Presenter(host_gpu_loss_callback), + provider_(provider), + guest_output_image_refresher_submission_tracker_(provider), + ui_submission_tracker_(provider), + paint_context_(provider) {} + + bool InitializeSurfaceIndependent(); + + [[nodiscard]] VkPipeline CreateGuestOutputPaintPipeline( + GuestOutputPaintEffect effect, VkRenderPass render_pass); + + VulkanProvider& provider_; + + // Static objects for guest output presentation, used only when painting the + // main target (can be destroyed only after awaiting main target usage + // completion). + VkDescriptorSetLayout guest_output_paint_image_descriptor_set_layout_ = + VK_NULL_HANDLE; + std::array + guest_output_paint_pipeline_layouts_ = {}; + VkShaderModule guest_output_paint_vs_ = VK_NULL_HANDLE; + std::array + guest_output_paint_fs_ = {}; + // Not compatible with the swapchain render pass even if the format is the + // same due to different dependencies (this is shader read > color + // attachment > shader read). + VkRenderPass guest_output_intermediate_render_pass_ = VK_NULL_HANDLE; + + // Value monotonically increased every time a new guest output image is + // initialized, for recreation of dependent objects such as framebuffers in + // the refreshers - saving and comparing the handle in the refresher is not + // enough as Create > Destroy > Create may result in the same handle for + // actually different objects without the refresher being aware of the + // destruction. + uint64_t guest_output_image_next_version_ = 0; + std::array + guest_output_images_; + VulkanSubmissionTracker guest_output_image_refresher_submission_tracker_; + + // UI submission tracker with the submission index that can be given to UI + // drawers (accessible from the UI thread only, at any time). + VulkanSubmissionTracker ui_submission_tracker_; + + // Accessible only by painting and by surface connection lifetime management + // (ConnectOrReconnectPaintingToSurfaceFromUIThread, + // DisconnectPaintingFromSurfaceFromUIThreadImpl) by the thread doing it, as + // well as by presenter initialization and shutdown. + PaintContext paint_context_; +}; + +} // namespace vulkan +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_D3D12_D3D12_PRESENTER_H_ diff --git a/src/xenia/ui/vulkan/vulkan_provider.cc b/src/xenia/ui/vulkan/vulkan_provider.cc index 1f974eedf..1b2a20b19 100644 --- a/src/xenia/ui/vulkan/vulkan_provider.cc +++ b/src/xenia/ui/vulkan/vulkan_provider.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -16,8 +16,10 @@ #include "xenia/base/assert.h" #include "xenia/base/cvar.h" #include "xenia/base/logging.h" +#include "xenia/base/math.h" #include "xenia/base/platform.h" -#include "xenia/ui/vulkan/vulkan_context.h" +#include "xenia/ui/vulkan/vulkan_immediate_drawer.h" +#include "xenia/ui/vulkan/vulkan_presenter.h" #if XE_PLATFORM_LINUX #include @@ -29,8 +31,21 @@ DEFINE_bool( vulkan_validation, true, "Enable Vulkan validation (VK_LAYER_KHRONOS_validation). Messages will be " - "written to the OS debug log.", + "written to the OS debug log without vulkan_debug_messenger or to the " + "Xenia log with it.", "Vulkan"); +DEFINE_bool( + vulkan_debug_utils_messenger, false, + "Enable writing Vulkan debug messages via VK_EXT_debug_utils to the Xenia " + "log.", + "Vulkan"); +DEFINE_uint32( + vulkan_debug_utils_messenger_severity, 2, + "Maximum severity of messages to log via the Vulkan debug messenger: 0 - " + "error, 1 - warning, 2 - info, 3 - verbose.", + "Vulkan"); +DEFINE_bool(vulkan_debug_utils_names, false, + "Enable naming Vulkan objects via VK_EXT_debug_utils.", "Vulkan"); DEFINE_int32( vulkan_device, -1, "Index of the physical device to use, or -1 for any compatible device.", @@ -40,8 +55,10 @@ namespace xe { namespace ui { namespace vulkan { -std::unique_ptr VulkanProvider::Create() { - std::unique_ptr provider(new VulkanProvider); +std::unique_ptr VulkanProvider::Create( + bool is_surface_required) { + std::unique_ptr provider( + new VulkanProvider(is_surface_required)); if (!provider->Initialize()) { xe::FatalError( "Unable to initialize Vulkan graphics subsystem.\n" @@ -68,6 +85,10 @@ VulkanProvider::~VulkanProvider() { ifn_.vkDestroyDevice(device_, nullptr); } if (instance_ != VK_NULL_HANDLE) { + if (debug_messenger_ != VK_NULL_HANDLE) { + ifn_.vkDestroyDebugUtilsMessengerEXT(instance_, debug_messenger_, + nullptr); + } lfn_.vkDestroyInstance(instance_, nullptr); } @@ -83,6 +104,8 @@ VulkanProvider::~VulkanProvider() { } bool VulkanProvider::Initialize() { + renderdoc_api_.Initialize(); + // Load the library. bool library_functions_loaded = true; #if XE_PLATFORM_LINUX @@ -128,6 +151,11 @@ bool VulkanProvider::Initialize() { lfn_.vkGetInstanceProcAddr( VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"))) != nullptr; + library_functions_loaded &= + (lfn_.vkEnumerateInstanceLayerProperties = + PFN_vkEnumerateInstanceLayerProperties(lfn_.vkGetInstanceProcAddr( + VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties"))) != + nullptr; if (!library_functions_loaded) { XELOGE( "Failed to get Vulkan library function pointers via " @@ -138,9 +166,6 @@ bool VulkanProvider::Initialize() { lfn_.vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion")); // Get the API version. - const uint32_t api_version_target = VK_MAKE_VERSION(1, 2, 148); - static_assert(VK_HEADER_VERSION_COMPLETE >= api_version_target, - "Vulkan header files must be up to date"); uint32_t instance_api_version; if (!lfn_.v_1_1.vkEnumerateInstanceVersion || lfn_.v_1_1.vkEnumerateInstanceVersion(&instance_api_version) != @@ -152,67 +177,127 @@ bool VulkanProvider::Initialize() { VK_VERSION_MINOR(instance_api_version), VK_VERSION_PATCH(instance_api_version)); - // Get the instance extensions. - std::vector instance_extension_properties; + // Get the instance extensions without layers, as well as extensions promoted + // to the core. + bool debug_utils_messenger_requested = cvars::vulkan_debug_utils_messenger; + bool debug_utils_names_requested = cvars::vulkan_debug_utils_names; + bool debug_utils_requested = + debug_utils_messenger_requested || debug_utils_names_requested; + std::memset(&instance_extensions_, 0, sizeof(instance_extensions_)); + if (instance_api_version >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { + instance_extensions_.khr_get_physical_device_properties2 = true; + } + std::vector instance_extensions_enabled; + std::vector instance_or_layer_extension_properties; VkResult instance_extensions_enumerate_result; for (;;) { uint32_t instance_extension_count = - uint32_t(instance_extension_properties.size()); - bool instance_extensions_was_empty = !instance_extension_count; + uint32_t(instance_or_layer_extension_properties.size()); + bool instance_extensions_were_empty = !instance_extension_count; instance_extensions_enumerate_result = lfn_.vkEnumerateInstanceExtensionProperties( nullptr, &instance_extension_count, - instance_extensions_was_empty + instance_extensions_were_empty ? nullptr - : instance_extension_properties.data()); - // If the original extension count was 0 (first call), SUCCESS is - // returned, not INCOMPLETE. + : instance_or_layer_extension_properties.data()); + // If the original extension count was 0 (first call), SUCCESS is returned, + // not INCOMPLETE. if (instance_extensions_enumerate_result == VK_SUCCESS || instance_extensions_enumerate_result == VK_INCOMPLETE) { - instance_extension_properties.resize(instance_extension_count); + instance_or_layer_extension_properties.resize(instance_extension_count); if (instance_extensions_enumerate_result == VK_SUCCESS && - (!instance_extensions_was_empty || !instance_extension_count)) { + (!instance_extensions_were_empty || !instance_extension_count)) { break; } } else { break; } } - if (instance_extensions_enumerate_result != VK_SUCCESS) { - instance_extension_properties.clear(); + if (instance_extensions_enumerate_result == VK_SUCCESS) { + AccumulateInstanceExtensions(instance_or_layer_extension_properties.size(), + instance_or_layer_extension_properties.data(), + debug_utils_requested, instance_extensions_, + instance_extensions_enabled); } - std::memset(&instance_extensions_, 0, sizeof(instance_extensions_)); - if (instance_api_version >= VK_MAKE_VERSION(1, 1, 0)) { - instance_extensions_.khr_get_physical_device_properties2 = true; - } - for (const VkExtensionProperties& instance_extension : - instance_extension_properties) { - const char* instance_extension_name = instance_extension.extensionName; - if (!instance_extensions_.khr_get_physical_device_properties2 && - !std::strcmp(instance_extension_name, - "VK_KHR_get_physical_device_properties2")) { - instance_extensions_.khr_get_physical_device_properties2 = true; + size_t instance_extensions_enabled_count_without_layers = + instance_extensions_enabled.size(); + InstanceExtensions instance_extensions_without_layers = instance_extensions_; + + // Get the instance layers and their extensions. + std::vector layer_properties; + VkResult layers_enumerate_result; + for (;;) { + uint32_t layer_count = uint32_t(layer_properties.size()); + bool layers_were_empty = !layer_count; + layers_enumerate_result = lfn_.vkEnumerateInstanceLayerProperties( + &layer_count, layers_were_empty ? nullptr : layer_properties.data()); + // If the original layer count was 0 (first call), SUCCESS is returned, not + // INCOMPLETE. + if (layers_enumerate_result == VK_SUCCESS || + layers_enumerate_result == VK_INCOMPLETE) { + layer_properties.resize(layer_count); + if (layers_enumerate_result == VK_SUCCESS && + (!layers_were_empty || !layer_count)) { + break; + } + } else { + break; + } + } + if (layers_enumerate_result != VK_SUCCESS) { + layer_properties.clear(); + } + struct { + bool khronos_validation; + } layer_enabled_flags = {}; + std::vector layers_enabled; + for (const VkLayerProperties& layer : layer_properties) { + // Check if the layer is needed. + // Checking if already enabled as an optimization to do fewer and fewer + // string comparisons. Adding literals to layers_enabled for the most C + // string lifetime safety. + if (!layer_enabled_flags.khronos_validation && cvars::vulkan_validation && + !std::strcmp(layer.layerName, "VK_LAYER_KHRONOS_validation")) { + layers_enabled.push_back("VK_LAYER_KHRONOS_validation"); + layer_enabled_flags.khronos_validation = true; + } else { + // Not enabling this layer, so don't need the extensions from it as well. + continue; + } + // Load extensions from the layer. + instance_or_layer_extension_properties.clear(); + for (;;) { + uint32_t instance_extension_count = + uint32_t(instance_or_layer_extension_properties.size()); + bool instance_extensions_were_empty = !instance_extension_count; + instance_extensions_enumerate_result = + lfn_.vkEnumerateInstanceExtensionProperties( + layer.layerName, &instance_extension_count, + instance_extensions_were_empty + ? nullptr + : instance_or_layer_extension_properties.data()); + // If the original extension count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (instance_extensions_enumerate_result == VK_SUCCESS || + instance_extensions_enumerate_result == VK_INCOMPLETE) { + instance_or_layer_extension_properties.resize(instance_extension_count); + if (instance_extensions_enumerate_result == VK_SUCCESS && + (!instance_extensions_were_empty || !instance_extension_count)) { + break; + } + } else { + break; + } + } + if (instance_extensions_enumerate_result == VK_SUCCESS) { + AccumulateInstanceExtensions( + instance_or_layer_extension_properties.size(), + instance_or_layer_extension_properties.data(), debug_utils_requested, + instance_extensions_, instance_extensions_enabled); } } - XELOGVK("Vulkan instance extensions:"); - XELOGVK( - "* VK_KHR_get_physical_device_properties2: {}", - instance_extensions_.khr_get_physical_device_properties2 ? "yes" : "no"); // Create the instance. - std::vector instance_extensions_enabled; - instance_extensions_enabled.push_back("VK_KHR_surface"); -#if XE_PLATFORM_ANDROID - instance_extensions_enabled.push_back("VK_KHR_android_surface"); -#elif XE_PLATFORM_WIN32 - instance_extensions_enabled.push_back("VK_KHR_win32_surface"); -#endif - if (instance_api_version < VK_MAKE_VERSION(1, 1, 0)) { - if (instance_extensions_.khr_get_physical_device_properties2) { - instance_extensions_enabled.push_back( - "VK_KHR_get_physical_device_properties2"); - } - } VkApplicationInfo application_info; application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; application_info.pNext = nullptr; @@ -224,22 +309,17 @@ bool VulkanProvider::Initialize() { // designed to use" // "Vulkan 1.0 implementations were required to return // VK_ERROR_INCOMPATIBLE_DRIVER if apiVersion was larger than 1.0" - application_info.apiVersion = instance_api_version >= VK_MAKE_VERSION(1, 1, 0) - ? api_version_target - : instance_api_version; + application_info.apiVersion = + instance_api_version >= VK_MAKE_API_VERSION(0, 1, 1, 0) + ? VK_HEADER_VERSION_COMPLETE + : instance_api_version; VkInstanceCreateInfo instance_create_info; instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_create_info.pNext = nullptr; instance_create_info.flags = 0; instance_create_info.pApplicationInfo = &application_info; - static const char* validation_layer = "VK_LAYER_KHRONOS_validation"; - if (cvars::vulkan_validation) { - instance_create_info.enabledLayerCount = 1; - instance_create_info.ppEnabledLayerNames = &validation_layer; - } else { - instance_create_info.enabledLayerCount = 0; - instance_create_info.ppEnabledLayerNames = nullptr; - } + instance_create_info.enabledLayerCount = uint32_t(layers_enabled.size()); + instance_create_info.ppEnabledLayerNames = layers_enabled.data(); instance_create_info.enabledExtensionCount = uint32_t(instance_extensions_enabled.size()); instance_create_info.ppEnabledExtensionNames = @@ -247,77 +327,187 @@ bool VulkanProvider::Initialize() { VkResult instance_create_result = lfn_.vkCreateInstance(&instance_create_info, nullptr, &instance_); if (instance_create_result != VK_SUCCESS) { - if (instance_create_result == VK_ERROR_LAYER_NOT_PRESENT) { - XELOGE("Failed to enable the Vulkan validation layer"); + if ((instance_create_result == VK_ERROR_LAYER_NOT_PRESENT || + instance_create_result == VK_ERROR_EXTENSION_NOT_PRESENT) && + !layers_enabled.empty()) { + XELOGE("Failed to enable Vulkan layers"); + // Try to create without layers and their extensions. + std::memset(&layer_enabled_flags, 0, sizeof(layer_enabled_flags)); instance_create_info.enabledLayerCount = 0; instance_create_info.ppEnabledLayerNames = nullptr; + instance_create_info.enabledExtensionCount = + uint32_t(instance_extensions_enabled_count_without_layers); + instance_extensions_ = instance_extensions_without_layers; instance_create_result = lfn_.vkCreateInstance(&instance_create_info, nullptr, &instance_); } if (instance_create_result != VK_SUCCESS) { - XELOGE("Failed to create a Vulkan instance with surface support"); + XELOGE("Failed to create a Vulkan instance"); return false; } } // Get instance functions. std::memset(&ifn_, 0, sizeof(ifn_)); - bool instance_functions_loaded = true; -#define XE_VULKAN_LOAD_IFN(name) \ - instance_functions_loaded &= \ - (ifn_.name = PFN_##name( \ - lfn_.vkGetInstanceProcAddr(instance_, #name))) != nullptr; -#define XE_VULKAN_LOAD_IFN_SYMBOL(name, symbol) \ - instance_functions_loaded &= \ - (ifn_.name = PFN_##name( \ - lfn_.vkGetInstanceProcAddr(instance_, symbol))) != nullptr; - XE_VULKAN_LOAD_IFN(vkCreateDevice); - XE_VULKAN_LOAD_IFN(vkDestroyDevice); - XE_VULKAN_LOAD_IFN(vkDestroySurfaceKHR); - XE_VULKAN_LOAD_IFN(vkEnumerateDeviceExtensionProperties); - XE_VULKAN_LOAD_IFN(vkEnumeratePhysicalDevices); - XE_VULKAN_LOAD_IFN(vkGetDeviceProcAddr); - XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceFeatures); - XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceProperties); - XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceMemoryProperties); - XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceQueueFamilyProperties); - XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); - XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceSurfaceFormatsKHR); - XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceSurfacePresentModesKHR); - XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceSurfaceSupportKHR); -#if XE_PLATFORM_ANDROID - XE_VULKAN_LOAD_IFN(vkCreateAndroidSurfaceKHR); -#elif XE_PLATFORM_WIN32 - XE_VULKAN_LOAD_IFN(vkCreateWin32SurfaceKHR); -#endif - if (instance_extensions_.khr_get_physical_device_properties2) { - XE_VULKAN_LOAD_IFN_SYMBOL(vkGetPhysicalDeviceProperties2KHR, - (instance_api_version >= VK_MAKE_VERSION(1, 1, 0)) - ? "vkGetPhysicalDeviceProperties2" - : "vkGetPhysicalDeviceProperties2KHR"); +#define XE_UI_VULKAN_FUNCTION(name) \ + functions_loaded &= (ifn_.name = PFN_##name(lfn_.vkGetInstanceProcAddr( \ + instance_, #name))) != nullptr; +#define XE_UI_VULKAN_FUNCTION_DONT_PROMOTE(extension_name, core_name) \ + functions_loaded &= \ + (ifn_.extension_name = PFN_##extension_name(lfn_.vkGetInstanceProcAddr( \ + instance_, #extension_name))) != nullptr; +#define XE_UI_VULKAN_FUNCTION_PROMOTE(extension_name, core_name) \ + functions_loaded &= \ + (ifn_.extension_name = PFN_##extension_name( \ + lfn_.vkGetInstanceProcAddr(instance_, #core_name))) != nullptr; + // Core - require unconditionally. + { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_1_0.inc" + if (!functions_loaded) { + XELOGE("Failed to get Vulkan instance function pointers"); + return false; + } } -#undef XE_VULKAN_LOAD_IFN_SYMBOL -#undef XE_VULKAN_LOAD_IFN - if (!instance_functions_loaded) { - XELOGE("Failed to get Vulkan instance function pointers"); + // Extensions - disable the specific extension if failed to get its functions. + if (instance_extensions_.ext_debug_utils) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_ext_debug_utils.inc" + instance_extensions_.ext_debug_utils = functions_loaded; + } + if (instance_extensions_.khr_get_physical_device_properties2) { + bool functions_loaded = true; + if (instance_api_version >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_PROMOTE +#include "xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } else { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#include "xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } + instance_extensions_.khr_get_physical_device_properties2 = functions_loaded; + } + if (instance_extensions_.khr_surface) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_khr_surface.inc" + instance_extensions_.khr_surface = functions_loaded; + } +#if XE_PLATFORM_ANDROID + if (instance_extensions_.khr_android_surface) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_khr_android_surface.inc" + instance_extensions_.khr_android_surface = functions_loaded; + } +#elif XE_PLATFORM_GNU_LINUX + if (instance_extensions_.khr_xcb_surface) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc" + instance_extensions_.khr_xcb_surface = functions_loaded; + } +#elif XE_PLATFORM_WIN32 + if (instance_extensions_.khr_win32_surface) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_khr_win32_surface.inc" + instance_extensions_.khr_win32_surface = functions_loaded; + } +#endif // XE_PLATFORM +#undef XE_UI_VULKAN_FUNCTION_PROMOTE +#undef XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#undef XE_UI_VULKAN_FUNCTION + + // Check if surface is supported after verifying that surface extension + // function pointers could be obtained. + if (is_surface_required_ && + !VulkanPresenter::GetSurfaceTypesSupportedByInstance( + instance_extensions_)) { + XELOGE( + "The Vulkan instance doesn't support the required surface extension " + "for the platform"); return false; } + // Report instance information after verifying that extension function + // pointers could be obtained. + XELOGVK("Vulkan layers enabled by Xenia:"); + XELOGVK("* VK_LAYER_KHRONOS_validation: {}", + layer_enabled_flags.khronos_validation ? "yes" : "no"); + XELOGVK("Vulkan instance extensions:"); + XELOGVK("* VK_EXT_debug_utils: {}", + instance_extensions_.ext_debug_utils + ? "yes" + : (debug_utils_requested ? "no" : "not requested")); + XELOGVK( + "* VK_KHR_get_physical_device_properties2: {}", + instance_extensions_.khr_get_physical_device_properties2 ? "yes" : "no"); + XELOGVK("* VK_KHR_surface: {}", + instance_extensions_.khr_surface ? "yes" : "no"); +#if XE_PLATFORM_ANDROID + XELOGVK(" * VK_KHR_android_surface: {}", + instance_extensions_.khr_android_surface ? "yes" : "no"); +#elif XE_PLATFORM_GNU_LINUX + XELOGVK(" * VK_KHR_xcb_surface: {}", + instance_extensions_.khr_xcb_surface ? "yes" : "no"); +#elif XE_PLATFORM_WIN32 + XELOGVK(" * VK_KHR_win32_surface: {}", + instance_extensions_.khr_win32_surface ? "yes" : "no"); +#endif + + // Enable the debug messenger. + if (debug_utils_messenger_requested) { + if (instance_extensions_.ext_debug_utils) { + VkDebugUtilsMessengerCreateInfoEXT debug_messenger_create_info; + debug_messenger_create_info.sType = + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + debug_messenger_create_info.pNext = nullptr; + debug_messenger_create_info.flags = 0; + debug_messenger_create_info.messageSeverity = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + if (cvars::vulkan_debug_utils_messenger_severity >= 1) { + debug_messenger_create_info.messageSeverity |= + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + if (cvars::vulkan_debug_utils_messenger_severity >= 2) { + debug_messenger_create_info.messageSeverity |= + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; + if (cvars::vulkan_debug_utils_messenger_severity >= 3) { + debug_messenger_create_info.messageSeverity |= + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; + } + } + } + debug_messenger_create_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; + debug_messenger_create_info.pfnUserCallback = DebugMessengerCallback; + debug_messenger_create_info.pUserData = this; + ifn_.vkCreateDebugUtilsMessengerEXT( + instance_, &debug_messenger_create_info, nullptr, &debug_messenger_); + } + if (debug_messenger_ != VK_NULL_HANDLE) { + XELOGVK("Vulkan debug messenger enabled"); + } else { + XELOGE("Failed to enable the Vulkan debug messenger"); + } + } + debug_names_used_ = + debug_utils_names_requested && instance_extensions_.ext_debug_utils; + // Get the compatible physical device. std::vector physical_devices; for (;;) { uint32_t physical_device_count = uint32_t(physical_devices.size()); - bool physical_devices_was_empty = !physical_device_count; + bool physical_devices_were_empty = !physical_device_count; VkResult physical_device_enumerate_result = ifn_.vkEnumeratePhysicalDevices( instance_, &physical_device_count, - physical_devices_was_empty ? nullptr : physical_devices.data()); + physical_devices_were_empty ? nullptr : physical_devices.data()); // If the original device count was 0 (first call), SUCCESS is returned, not // INCOMPLETE. if (physical_device_enumerate_result == VK_SUCCESS || physical_device_enumerate_result == VK_INCOMPLETE) { physical_devices.resize(physical_device_count); if (physical_device_enumerate_result == VK_SUCCESS && - (!physical_devices_was_empty || !physical_device_count)) { + (!physical_devices_were_empty || !physical_device_count)) { break; } } else { @@ -345,14 +535,16 @@ bool VulkanProvider::Initialize() { physical_device_index_last = physical_devices.size() - 1; } physical_device_ = VK_NULL_HANDLE; - std::vector queue_families; - uint32_t queue_family_sparse_binding = UINT32_MAX; + std::vector queue_families_properties; std::vector device_extension_properties; + std::vector device_extensions_enabled; for (size_t i = physical_device_index_first; i <= physical_device_index_last; ++i) { VkPhysicalDevice physical_device_current = physical_devices[i]; // Get physical device features and check if the needed ones are supported. + // Need this before obtaining the queues as sparse binding is an optional + // feature. ifn_.vkGetPhysicalDeviceFeatures(physical_device_current, &device_features_); // Passing indices directly from guest memory, where they are big-endian; a @@ -367,66 +559,106 @@ bool VulkanProvider::Initialize() { continue; } - // Get the graphics and compute queue, and also a sparse binding queue - // (preferably the same for the least latency between the two, as Xenia - // submits sparse binding commands right before graphics commands anyway). + // Get the needed queues: + // - Graphics and compute. + // - Sparse binding if used (preferably the same as the graphics and compute + // one for the lowest latency as Xenia submits sparse binding commands + // right before graphics commands anyway). + // - Additional queues for presentation as VulkanProvider may be used with + // different surfaces, and they may have varying support of presentation + // from different queue families. uint32_t queue_family_count = 0; ifn_.vkGetPhysicalDeviceQueueFamilyProperties(physical_device_current, &queue_family_count, nullptr); - queue_families.resize(queue_family_count); + queue_families_properties.resize(queue_family_count); ifn_.vkGetPhysicalDeviceQueueFamilyProperties( - physical_device_current, &queue_family_count, queue_families.data()); - assert_true(queue_family_count == queue_families.size()); - queue_family_graphics_compute_ = UINT32_MAX; - queue_family_sparse_binding = UINT32_MAX; - constexpr VkQueueFlags flags_graphics_compute = - VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT; - constexpr VkQueueFlags flags_graphics_compute_sparse = - flags_graphics_compute | VK_QUEUE_SPARSE_BINDING_BIT; + physical_device_current, &queue_family_count, + queue_families_properties.data()); + assert_true(queue_family_count == queue_families_properties.size()); + // Initialize all queue families to unused. + queue_families_.clear(); + queue_families_.resize(queue_family_count); + // First, try to obtain a graphics and compute queue. Preferably find a + // queue with sparse binding support as well. + // The family indices here are listed from the best to the worst. + uint32_t queue_family_graphics_compute_sparse_binding = UINT32_MAX; + uint32_t queue_family_graphics_compute_only = UINT32_MAX; for (uint32_t j = 0; j < queue_family_count; ++j) { - VkQueueFlags queue_flags = queue_families[j].queueFlags; - if (device_features_.sparseBinding) { - // First, check if the queue family supports both graphics/compute and - // sparse binding. This would be the best for Xenia. - if ((queue_flags & flags_graphics_compute_sparse) == - flags_graphics_compute_sparse) { - queue_family_graphics_compute_ = j; - queue_family_sparse_binding = j; - break; - } - // If not supporting both, for sparse binding, for now (until a queue - // supporting all three is found), pick the first queue supporting it. - if ((queue_flags & VK_QUEUE_SPARSE_BINDING_BIT) && - queue_family_sparse_binding == UINT32_MAX) { - queue_family_sparse_binding = j; - } + const VkQueueFamilyProperties& queue_family_properties = + queue_families_properties[j]; + if ((queue_family_properties.queueFlags & + (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)) != + (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)) { + continue; } - // If the device supports sparse binding, for now (until a queue - // supporting all three is found), pick the first queue supporting - // graphics/compute for graphics. - // If it doesn't, just pick the first queue supporting graphics/compute. - if ((queue_flags & flags_graphics_compute) == flags_graphics_compute && - queue_family_graphics_compute_ == UINT32_MAX) { - queue_family_graphics_compute_ = j; - if (!device_features_.sparseBinding) { - break; - } + uint32_t* queue_family_ptr; + if (device_features_.sparseBinding && + (queue_family_properties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT)) { + queue_family_ptr = &queue_family_graphics_compute_sparse_binding; + } else { + queue_family_ptr = &queue_family_graphics_compute_only; + } + if (*queue_family_ptr == UINT32_MAX) { + *queue_family_ptr = j; } } - // FIXME(Triang3l): Here we're assuming that the graphics/compute queue - // family supports presentation to the surface. It is probably true for most - // target Vulkan implementations, however, there are no guarantees in the - // specification. - // To check if the queue supports presentation, the target surface must - // exist at this point. However, the actual window that is created in - // GraphicsContext, not in GraphicsProvider. - // While we do have main_window here, it's not necessarily the window that - // presentation will actually happen to. Also, while on Windows the HWND is - // persistent, on Android, ANativeWindow is destroyed whenever the activity - // goes to background, and the application may even be started in background - // (programmatically, or using ADB, while the device is locked), thus the - // window doesn't necessarily exist at this point. - if (queue_family_graphics_compute_ == UINT32_MAX) { + if (queue_family_graphics_compute_sparse_binding != UINT32_MAX) { + assert_true(device_features_.sparseBinding); + queue_family_graphics_compute_ = + queue_family_graphics_compute_sparse_binding; + } else if (queue_family_graphics_compute_only != UINT32_MAX) { + queue_family_graphics_compute_ = queue_family_graphics_compute_only; + } else { + // No graphics and compute queue family. + continue; + } + // Mark the graphics and compute queue as requested. + queue_families_[queue_family_graphics_compute_].queue_count = + std::max(queue_families_[queue_family_graphics_compute_].queue_count, + uint32_t(1)); + // Request a separate sparse binding queue if needed. + queue_family_sparse_binding_ = UINT32_MAX; + if (device_features_.sparseBinding) { + if (queue_families_properties[queue_family_graphics_compute_].queueFlags & + VK_QUEUE_SPARSE_BINDING_BIT) { + queue_family_sparse_binding_ = queue_family_graphics_compute_; + } else { + for (uint32_t j = 0; j < queue_family_count; ++j) { + if (!(queue_families_properties[j].queueFlags & + VK_QUEUE_SPARSE_BINDING_BIT)) { + continue; + } + queue_family_sparse_binding_ = j; + queue_families_[j].queue_count = + std::max(queue_families_[j].queue_count, uint32_t(1)); + break; + } + } + // Don't expose, and disable during logical device creature, the sparse + // binding feature if failed to obtain a queue supporting it. + if (queue_family_sparse_binding_ == UINT32_MAX) { + device_features_.sparseBinding = VK_FALSE; + } + } + bool any_queue_potentially_supports_present = false; + if (instance_extensions_.khr_surface) { + // Request possible presentation queues. + for (uint32_t j = 0; j < queue_family_count; ++j) { +#if XE_PLATFORM_WIN32 + if (instance_extensions_.khr_win32_surface && + !ifn_.vkGetPhysicalDeviceWin32PresentationSupportKHR( + physical_device_current, j)) { + continue; + } +#endif + any_queue_potentially_supports_present = true; + QueueFamily& queue_family = queue_families_[j]; + queue_family.queue_count = + std::max(queue_families_[j].queue_count, uint32_t(1)); + queue_family.potentially_supports_present = true; + } + } + if (!any_queue_potentially_supports_present && is_surface_required_) { continue; } @@ -441,19 +673,20 @@ bool VulkanProvider::Initialize() { for (;;) { uint32_t device_extension_count = uint32_t(device_extension_properties.size()); - bool device_extensions_was_empty = !device_extension_count; + bool device_extensions_were_empty = !device_extension_count; device_extensions_enumerate_result = ifn_.vkEnumerateDeviceExtensionProperties( physical_device_current, nullptr, &device_extension_count, - device_extensions_was_empty ? nullptr - : device_extension_properties.data()); + device_extensions_were_empty + ? nullptr + : device_extension_properties.data()); // If the original extension count was 0 (first call), SUCCESS is // returned, not INCOMPLETE. if (device_extensions_enumerate_result == VK_SUCCESS || device_extensions_enumerate_result == VK_INCOMPLETE) { device_extension_properties.resize(device_extension_count); if (device_extensions_enumerate_result == VK_SUCCESS && - (!device_extensions_was_empty || !device_extension_count)) { + (!device_extensions_were_empty || !device_extension_count)) { break; } } else { @@ -464,38 +697,53 @@ bool VulkanProvider::Initialize() { continue; } std::memset(&device_extensions_, 0, sizeof(device_extensions_)); - if (device_properties_.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) { + if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { device_extensions_.khr_dedicated_allocation = true; - if (device_properties_.apiVersion >= VK_MAKE_VERSION(1, 2, 0)) { + if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 2, 0)) { + device_extensions_.khr_image_format_list = true; device_extensions_.khr_shader_float_controls = true; device_extensions_.khr_spirv_1_4 = true; } } - bool device_supports_swapchain = false; + device_extensions_enabled.clear(); for (const VkExtensionProperties& device_extension : device_extension_properties) { const char* device_extension_name = device_extension.extensionName; + // Checking if already enabled as an optimization to do fewer and fewer + // string comparisons, as well as to skip adding extensions promoted to + // the core to device_extensions_enabled. Adding literals to + // device_extensions_enabled for the most C string lifetime safety. if (!device_extensions_.ext_fragment_shader_interlock && !std::strcmp(device_extension_name, "VK_EXT_fragment_shader_interlock")) { + device_extensions_enabled.push_back("VK_EXT_fragment_shader_interlock"); device_extensions_.ext_fragment_shader_interlock = true; } else if (!device_extensions_.khr_dedicated_allocation && !std::strcmp(device_extension_name, "VK_KHR_dedicated_allocation")) { + device_extensions_enabled.push_back("VK_KHR_dedicated_allocation"); device_extensions_.khr_dedicated_allocation = true; + } else if (!device_extensions_.khr_image_format_list && + !std::strcmp(device_extension_name, + "VK_KHR_image_format_list")) { + device_extensions_enabled.push_back("VK_KHR_image_format_list"); + device_extensions_.khr_image_format_list = true; } else if (!device_extensions_.khr_shader_float_controls && !std::strcmp(device_extension_name, "VK_KHR_shader_float_controls")) { + device_extensions_enabled.push_back("VK_KHR_shader_float_controls"); device_extensions_.khr_shader_float_controls = true; } else if (!device_extensions_.khr_spirv_1_4 && !std::strcmp(device_extension_name, "VK_KHR_spirv_1_4")) { + device_extensions_enabled.push_back("VK_KHR_spirv_1_4"); device_extensions_.khr_spirv_1_4 = true; - } else if (!device_supports_swapchain && + } else if (!device_extensions_.khr_swapchain && !std::strcmp(device_extension_name, "VK_KHR_swapchain")) { - device_supports_swapchain = true; + device_extensions_enabled.push_back("VK_KHR_swapchain"); + device_extensions_.khr_swapchain = true; } } - if (!device_supports_swapchain) { + if (is_surface_required_ && !device_extensions_.khr_swapchain) { continue; } @@ -564,81 +812,40 @@ bool VulkanProvider::Initialize() { } } - XELOGVK( - "Vulkan device: {} (vendor {:04X}, device {:04X}, driver {:08X}, API " - "{}.{}.{})", - device_properties_.deviceName, device_properties_.vendorID, - device_properties_.deviceID, device_properties_.driverVersion, - VK_VERSION_MAJOR(device_properties_.apiVersion), - VK_VERSION_MINOR(device_properties_.apiVersion), - VK_VERSION_PATCH(device_properties_.apiVersion)); - XELOGVK("Vulkan device extensions:"); - XELOGVK("* VK_EXT_fragment_shader_interlock: {}", - device_extensions_.ext_fragment_shader_interlock ? "yes" : "no"); - XELOGVK("* VK_KHR_dedicated_allocation: {}", - device_extensions_.khr_dedicated_allocation ? "yes" : "no"); - XELOGVK("* VK_KHR_shader_float_controls: {}", - device_extensions_.khr_shader_float_controls ? "yes" : "no"); - XELOGVK("* VK_KHR_spirv_1_4: {}", - device_extensions_.khr_spirv_1_4 ? "yes" : "no"); - if (device_extensions_.khr_shader_float_controls) { - XELOGVK( - "* Signed zero, inf, nan preserve for float32: {}", - device_float_controls_properties_.shaderSignedZeroInfNanPreserveFloat32 - ? "yes" - : "no"); - XELOGVK("* Denorm flush to zero for float32: {}", - device_float_controls_properties_.shaderDenormFlushToZeroFloat32 - ? "yes" - : "no"); - } - // TODO(Triang3l): Report properties, features. - // Create the device. - float queue_priority_high = 1.0f; - VkDeviceQueueCreateInfo queue_create_infos[2]; - queue_create_infos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[0].pNext = nullptr; - queue_create_infos[0].flags = 0; - queue_create_infos[0].queueFamilyIndex = queue_family_graphics_compute_; - queue_create_infos[0].queueCount = 1; - queue_create_infos[0].pQueuePriorities = &queue_priority_high; - bool separate_sparse_binding_queue = - queue_family_sparse_binding != UINT32_MAX && - queue_family_sparse_binding != queue_family_graphics_compute_; - if (separate_sparse_binding_queue) { - queue_create_infos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[1].pNext = nullptr; - queue_create_infos[1].flags = 0; - queue_create_infos[1].queueFamilyIndex = queue_family_sparse_binding; - queue_create_infos[1].queueCount = 1; - queue_create_infos[1].pQueuePriorities = &queue_priority_high; + std::vector queue_create_infos; + queue_create_infos.reserve(queue_families_.size()); + uint32_t used_queue_count = 0; + uint32_t max_queue_count_per_family = 0; + for (size_t i = 0; i < queue_families_.size(); ++i) { + QueueFamily& queue_family = queue_families_[i]; + queue_family.queue_first_index = used_queue_count; + if (!queue_family.queue_count) { + continue; + } + VkDeviceQueueCreateInfo& queue_create_info = + queue_create_infos.emplace_back(); + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.pNext = nullptr; + queue_create_info.flags = 0; + queue_create_info.queueFamilyIndex = uint32_t(i); + queue_create_info.queueCount = queue_family.queue_count; + // pQueuePriorities will be set later based on max_queue_count_per_family. + max_queue_count_per_family = + std::max(max_queue_count_per_family, queue_family.queue_count); + used_queue_count += queue_family.queue_count; } - std::vector device_extensions_enabled; - device_extensions_enabled.push_back("VK_KHR_swapchain"); - if (device_extensions_.ext_fragment_shader_interlock) { - device_extensions_enabled.push_back("VK_EXT_fragment_shader_interlock"); - } - if (device_properties_.apiVersion < VK_MAKE_VERSION(1, 2, 0)) { - if (device_properties_.apiVersion < VK_MAKE_VERSION(1, 1, 0)) { - if (device_extensions_.khr_dedicated_allocation) { - device_extensions_enabled.push_back("VK_KHR_dedicated_allocation"); - } - } - if (device_extensions_.khr_shader_float_controls) { - device_extensions_enabled.push_back("VK_KHR_shader_float_controls"); - } - if (device_extensions_.khr_spirv_1_4) { - device_extensions_enabled.push_back("VK_KHR_spirv_1_4"); - } + std::vector queue_priorities; + queue_priorities.resize(max_queue_count_per_family, 1.0f); + for (VkDeviceQueueCreateInfo& queue_create_info : queue_create_infos) { + queue_create_info.pQueuePriorities = queue_priorities.data(); } VkDeviceCreateInfo device_create_info; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.pNext = nullptr; device_create_info.flags = 0; - device_create_info.queueCreateInfoCount = - separate_sparse_binding_queue ? 2 : 1; - device_create_info.pQueueCreateInfos = queue_create_infos; + device_create_info.queueCreateInfoCount = uint32_t(queue_create_infos.size()); + device_create_info.pQueueCreateInfos = queue_create_infos.data(); // Device layers are deprecated - using validation layer on the instance. device_create_info.enabledLayerCount = 0; device_create_info.ppEnabledLayerNames = nullptr; @@ -654,98 +861,102 @@ bool VulkanProvider::Initialize() { } // Get device functions. + std::memset(&dfn_, 0, sizeof(ifn_)); bool device_functions_loaded = true; -#define XE_VULKAN_LOAD_DFN(name) \ - device_functions_loaded &= \ +#define XE_UI_VULKAN_FUNCTION(name) \ + functions_loaded &= \ (dfn_.name = PFN_##name(ifn_.vkGetDeviceProcAddr(device_, #name))) != \ nullptr; - XE_VULKAN_LOAD_DFN(vkAcquireNextImageKHR); - XE_VULKAN_LOAD_DFN(vkAllocateCommandBuffers); - XE_VULKAN_LOAD_DFN(vkAllocateDescriptorSets); - XE_VULKAN_LOAD_DFN(vkAllocateMemory); - XE_VULKAN_LOAD_DFN(vkBeginCommandBuffer); - XE_VULKAN_LOAD_DFN(vkBindBufferMemory); - XE_VULKAN_LOAD_DFN(vkBindImageMemory); - XE_VULKAN_LOAD_DFN(vkCmdBeginRenderPass); - XE_VULKAN_LOAD_DFN(vkCmdBindDescriptorSets); - XE_VULKAN_LOAD_DFN(vkCmdBindIndexBuffer); - XE_VULKAN_LOAD_DFN(vkCmdBindPipeline); - XE_VULKAN_LOAD_DFN(vkCmdBindVertexBuffers); - XE_VULKAN_LOAD_DFN(vkCmdClearColorImage); - XE_VULKAN_LOAD_DFN(vkCmdCopyBuffer); - XE_VULKAN_LOAD_DFN(vkCmdCopyBufferToImage); - XE_VULKAN_LOAD_DFN(vkCmdDraw); - XE_VULKAN_LOAD_DFN(vkCmdDrawIndexed); - XE_VULKAN_LOAD_DFN(vkCmdEndRenderPass); - XE_VULKAN_LOAD_DFN(vkCmdPipelineBarrier); - XE_VULKAN_LOAD_DFN(vkCmdPushConstants); - XE_VULKAN_LOAD_DFN(vkCmdSetScissor); - XE_VULKAN_LOAD_DFN(vkCmdSetViewport); - XE_VULKAN_LOAD_DFN(vkCreateBuffer); - XE_VULKAN_LOAD_DFN(vkCreateCommandPool); - XE_VULKAN_LOAD_DFN(vkCreateDescriptorPool); - XE_VULKAN_LOAD_DFN(vkCreateDescriptorSetLayout); - XE_VULKAN_LOAD_DFN(vkCreateFence); - XE_VULKAN_LOAD_DFN(vkCreateFramebuffer); - XE_VULKAN_LOAD_DFN(vkCreateGraphicsPipelines); - XE_VULKAN_LOAD_DFN(vkCreateImage); - XE_VULKAN_LOAD_DFN(vkCreateImageView); - XE_VULKAN_LOAD_DFN(vkCreatePipelineLayout); - XE_VULKAN_LOAD_DFN(vkCreateRenderPass); - XE_VULKAN_LOAD_DFN(vkCreateSampler); - XE_VULKAN_LOAD_DFN(vkCreateSemaphore); - XE_VULKAN_LOAD_DFN(vkCreateShaderModule); - XE_VULKAN_LOAD_DFN(vkCreateSwapchainKHR); - XE_VULKAN_LOAD_DFN(vkDestroyBuffer); - XE_VULKAN_LOAD_DFN(vkDestroyCommandPool); - XE_VULKAN_LOAD_DFN(vkDestroyDescriptorPool); - XE_VULKAN_LOAD_DFN(vkDestroyDescriptorSetLayout); - XE_VULKAN_LOAD_DFN(vkDestroyFence); - XE_VULKAN_LOAD_DFN(vkDestroyFramebuffer); - XE_VULKAN_LOAD_DFN(vkDestroyImage); - XE_VULKAN_LOAD_DFN(vkDestroyImageView); - XE_VULKAN_LOAD_DFN(vkDestroyPipeline); - XE_VULKAN_LOAD_DFN(vkDestroyPipelineLayout); - XE_VULKAN_LOAD_DFN(vkDestroyRenderPass); - XE_VULKAN_LOAD_DFN(vkDestroySampler); - XE_VULKAN_LOAD_DFN(vkDestroySemaphore); - XE_VULKAN_LOAD_DFN(vkDestroyShaderModule); - XE_VULKAN_LOAD_DFN(vkDestroySwapchainKHR); - XE_VULKAN_LOAD_DFN(vkEndCommandBuffer); - XE_VULKAN_LOAD_DFN(vkFlushMappedMemoryRanges); - XE_VULKAN_LOAD_DFN(vkFreeMemory); - XE_VULKAN_LOAD_DFN(vkGetBufferMemoryRequirements); - XE_VULKAN_LOAD_DFN(vkGetDeviceQueue); - XE_VULKAN_LOAD_DFN(vkGetImageMemoryRequirements); - XE_VULKAN_LOAD_DFN(vkGetSwapchainImagesKHR); - XE_VULKAN_LOAD_DFN(vkMapMemory); - XE_VULKAN_LOAD_DFN(vkResetCommandPool); - XE_VULKAN_LOAD_DFN(vkResetDescriptorPool); - XE_VULKAN_LOAD_DFN(vkResetFences); - XE_VULKAN_LOAD_DFN(vkQueueBindSparse); - XE_VULKAN_LOAD_DFN(vkQueuePresentKHR); - XE_VULKAN_LOAD_DFN(vkQueueSubmit); - XE_VULKAN_LOAD_DFN(vkUnmapMemory); - XE_VULKAN_LOAD_DFN(vkUpdateDescriptorSets); - XE_VULKAN_LOAD_DFN(vkWaitForFences); -#undef XE_VULKAN_LOAD_DFN +#define XE_UI_VULKAN_FUNCTION_DONT_PROMOTE(extension_name, core_name) \ + functions_loaded &= \ + (dfn_.extension_name = PFN_##extension_name( \ + ifn_.vkGetDeviceProcAddr(device_, #extension_name))) != nullptr; +#define XE_UI_VULKAN_FUNCTION_PROMOTE(extension_name, core_name) \ + functions_loaded &= \ + (dfn_.extension_name = PFN_##extension_name( \ + ifn_.vkGetDeviceProcAddr(device_, #core_name))) != nullptr; + // Core - require unconditionally. + { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/device_1_0.inc" + if (!functions_loaded) { + XELOGE("Failed to get Vulkan device function pointers"); + return false; + } + } + // Extensions - disable the specific extension if failed to get its functions. + if (device_extensions_.khr_swapchain) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/device_khr_swapchain.inc" + if (!functions_loaded) { + // Outside the physical device selection loop, so can't just skip the + // device anymore, but this shouldn't really happen anyway. + XELOGE( + "Failed to get Vulkan swapchain function pointers while swapchain " + "support is required"); + return false; + } + device_extensions_.khr_swapchain = functions_loaded; + } +#undef XE_UI_VULKAN_FUNCTION_PROMOTE +#undef XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#undef XE_UI_VULKAN_FUNCTION if (!device_functions_loaded) { XELOGE("Failed to get Vulkan device function pointers"); return false; } + // Report device information after verifying that extension function pointers + // could be obtained. + XELOGVK( + "Vulkan device: {} (vendor {:04X}, device {:04X}, driver {:08X}, API " + "{}.{}.{})", + device_properties_.deviceName, device_properties_.vendorID, + device_properties_.deviceID, device_properties_.driverVersion, + VK_VERSION_MAJOR(device_properties_.apiVersion), + VK_VERSION_MINOR(device_properties_.apiVersion), + VK_VERSION_PATCH(device_properties_.apiVersion)); + XELOGVK("Vulkan device extensions:"); + XELOGVK("* VK_EXT_fragment_shader_interlock: {}", + device_extensions_.ext_fragment_shader_interlock ? "yes" : "no"); + XELOGVK("* VK_KHR_dedicated_allocation: {}", + device_extensions_.khr_dedicated_allocation ? "yes" : "no"); + XELOGVK("* VK_KHR_image_format_list: {}", + device_extensions_.khr_image_format_list ? "yes" : "no"); + XELOGVK("* VK_KHR_shader_float_controls: {}", + device_extensions_.khr_shader_float_controls ? "yes" : "no"); + if (device_extensions_.khr_shader_float_controls) { + XELOGVK( + " * Signed zero, inf, nan preserve for float32: {}", + device_float_controls_properties_.shaderSignedZeroInfNanPreserveFloat32 + ? "yes" + : "no"); + XELOGVK(" * Denorm flush to zero for float32: {}", + device_float_controls_properties_.shaderDenormFlushToZeroFloat32 + ? "yes" + : "no"); + XELOGVK("* VK_KHR_spirv_1_4: {}", + device_extensions_.khr_spirv_1_4 ? "yes" : "no"); + XELOGVK("* VK_KHR_swapchain: {}", + device_extensions_.khr_swapchain ? "yes" : "no"); + } + // TODO(Triang3l): Report properties, features. + // Get the queues. - dfn_.vkGetDeviceQueue(device_, queue_family_graphics_compute_, 0, - &queue_graphics_compute_); - if (queue_family_sparse_binding != UINT32_MAX) { - if (separate_sparse_binding_queue) { - dfn_.vkGetDeviceQueue(device_, queue_family_sparse_binding, 0, - &queue_sparse_binding_); - } else { - queue_sparse_binding_ = queue_graphics_compute_; + queues_.reset(); + queues_ = std::make_unique(used_queue_count); + uint32_t queue_index = 0; + for (size_t i = 0; i < queue_families_.size(); ++i) { + const QueueFamily& queue_family = queue_families_[i]; + if (!queue_family.queue_count) { + continue; + } + assert_true(queue_index == queue_family.queue_first_index); + for (uint32_t j = 0; j < queue_family.queue_count; ++j) { + VkQueue queue; + dfn_.vkGetDeviceQueue(device_, uint32_t(i), j, &queue); + queues_[queue_index++].queue = queue; } - } else { - queue_sparse_binding_ = VK_NULL_HANDLE; } // Create host-side samplers. @@ -795,23 +1006,136 @@ bool VulkanProvider::Initialize() { return true; } -std::unique_ptr VulkanProvider::CreateHostContext( - Window* target_window) { - auto new_context = - std::unique_ptr(new VulkanContext(this, target_window)); - if (!new_context->Initialize()) { - return nullptr; - } - return std::unique_ptr(new_context.release()); +std::unique_ptr VulkanProvider::CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback) { + return VulkanPresenter::Create(host_gpu_loss_callback, *this); } -std::unique_ptr VulkanProvider::CreateEmulationContext() { - auto new_context = - std::unique_ptr(new VulkanContext(this, nullptr)); - if (!new_context->Initialize()) { - return nullptr; +std::unique_ptr VulkanProvider::CreateImmediateDrawer() { + return VulkanImmediateDrawer::Create(*this); +} + +void VulkanProvider::SetDeviceObjectName(VkObjectType type, uint64_t handle, + const char* name) const { + if (!debug_names_used_) { + return; } - return std::unique_ptr(new_context.release()); + VkDebugUtilsObjectNameInfoEXT name_info; + name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + name_info.pNext = nullptr; + name_info.objectType = type; + name_info.objectHandle = handle; + name_info.pObjectName = name; + ifn_.vkSetDebugUtilsObjectNameEXT(device_, &name_info); +} + +void VulkanProvider::AccumulateInstanceExtensions( + size_t properties_count, const VkExtensionProperties* properties, + bool request_debug_utils, InstanceExtensions& instance_extensions, + std::vector& instance_extensions_enabled) { + for (size_t i = 0; i < properties_count; ++i) { + const char* instance_extension_name = properties[i].extensionName; + // Checking if already enabled as an optimization to do fewer and fewer + // string comparisons, as well as to skip adding extensions promoted to the + // core to instance_extensions_enabled. Adding literals to + // instance_extensions_enabled for the most C string lifetime safety. + if (request_debug_utils && !instance_extensions.ext_debug_utils && + !std::strcmp(instance_extension_name, "VK_EXT_debug_utils")) { + // Debug utilities are only enabled when needed. Overhead in Xenia not + // profiled, but better to avoid unless enabled by the user. + instance_extensions_enabled.push_back("VK_EXT_debug_utils"); + instance_extensions.ext_debug_utils = true; + } else if (!instance_extensions.khr_get_physical_device_properties2 && + !std::strcmp(instance_extension_name, + "VK_KHR_get_physical_device_properties2")) { + instance_extensions_enabled.push_back( + "VK_KHR_get_physical_device_properties2"); + instance_extensions.khr_get_physical_device_properties2 = true; + } else if (!instance_extensions.khr_surface && + !std::strcmp(instance_extension_name, "VK_KHR_surface")) { + instance_extensions_enabled.push_back("VK_KHR_surface"); + instance_extensions.khr_surface = true; + } else { +#if XE_PLATFORM_ANDROID + if (!instance_extensions.khr_android_surface && + !std::strcmp(instance_extension_name, "VK_KHR_android_surface")) { + instance_extensions_enabled.push_back("VK_KHR_android_surface"); + instance_extensions.khr_android_surface = true; + } +#elif XE_PLATFORM_GNU_LINUX + if (!instance_extensions.khr_xcb_surface && + !std::strcmp(instance_extension_name, "VK_KHR_xcb_surface")) { + instance_extensions_enabled.push_back("VK_KHR_xcb_surface"); + instance_extensions.khr_xcb_surface = true; + } +#elif XE_PLATFORM_WIN32 + if (!instance_extensions.khr_win32_surface && + !std::strcmp(instance_extension_name, "VK_KHR_win32_surface")) { + instance_extensions_enabled.push_back("VK_KHR_win32_surface"); + instance_extensions.khr_win32_surface = true; + } +#endif + } + } +} + +VkBool32 VKAPI_CALL VulkanProvider::DebugMessengerCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_types, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* user_data) { + const char* severity_string; + switch (message_severity) { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + severity_string = "verbose output"; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + severity_string = "info"; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + severity_string = "warning"; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + severity_string = "error"; + break; + default: + switch (xe::bit_count(uint32_t(message_severity))) { + case 0: + severity_string = "no-severity"; + break; + case 1: + severity_string = "unknown-severity"; + break; + default: + severity_string = "multi-severity"; + } + } + const char* type_string; + switch (message_types) { + case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: + type_string = "general"; + break; + case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: + type_string = "validation"; + break; + case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: + type_string = "performance"; + break; + default: + switch (xe::bit_count(uint32_t(message_types))) { + case 0: + type_string = "no-type"; + break; + case 1: + type_string = "unknown-type"; + break; + default: + type_string = "multi-type"; + } + } + XELOGVK("Vulkan {} {}: {}", type_string, severity_string, + callback_data->pMessage); + return VK_FALSE; } } // namespace vulkan diff --git a/src/xenia/ui/vulkan/vulkan_provider.h b/src/xenia/ui/vulkan/vulkan_provider.h index cb3db6a4e..741cbb384 100644 --- a/src/xenia/ui/vulkan/vulkan_provider.h +++ b/src/xenia/ui/vulkan/vulkan_provider.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,19 +10,26 @@ #ifndef XENIA_UI_VULKAN_VULKAN_PROVIDER_H_ #define XENIA_UI_VULKAN_VULKAN_PROVIDER_H_ +#include #include #include #include +#include #include #include "xenia/base/assert.h" #include "xenia/base/platform.h" #include "xenia/ui/graphics_provider.h" +#include "xenia/ui/renderdoc_api.h" #if XE_PLATFORM_ANDROID #ifndef VK_USE_PLATFORM_ANDROID_KHR #define VK_USE_PLATFORM_ANDROID_KHR 1 #endif +#elif XE_PLATFORM_GNU_LINUX +#ifndef VK_USE_PLATFORM_XCB_KHR +#define VK_USE_PLATFORM_XCB_KHR 1 +#endif #elif XE_PLATFORM_WIN32 // Must be included before vulkan.h with VK_USE_PLATFORM_WIN32_KHR because it // includes Windows.h too. @@ -47,13 +54,17 @@ namespace vulkan { class VulkanProvider : public GraphicsProvider { public: - ~VulkanProvider() override; + ~VulkanProvider(); - static std::unique_ptr Create(); + static std::unique_ptr Create(bool is_surface_required); - std::unique_ptr CreateHostContext( - Window* target_window) override; - std::unique_ptr CreateEmulationContext() override; + std::unique_ptr CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback = + Presenter::FatalErrorHostGpuLossCallback) override; + + std::unique_ptr CreateImmediateDrawer() override; + + const RenderdocApi& renderdoc_api() const { return renderdoc_api_; } struct LibraryFunctions { // From the module. @@ -63,6 +74,7 @@ class VulkanProvider : public GraphicsProvider { PFN_vkCreateInstance vkCreateInstance; PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; + PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; struct { PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; } v_1_1; @@ -70,41 +82,41 @@ class VulkanProvider : public GraphicsProvider { const LibraryFunctions& lfn() const { return lfn_; } struct InstanceExtensions { + bool ext_debug_utils; // Core since 1.1.0. bool khr_get_physical_device_properties2; + + // Surface extensions. + bool khr_surface; +#if XE_PLATFORM_ANDROID + bool khr_android_surface; +#elif XE_PLATFORM_GNU_LINUX + bool khr_xcb_surface; +#elif XE_PLATFORM_WIN32 + bool khr_win32_surface; +#endif }; const InstanceExtensions& instance_extensions() const { return instance_extensions_; } VkInstance instance() const { return instance_; } struct InstanceFunctions { - PFN_vkCreateDevice vkCreateDevice; - PFN_vkDestroyDevice vkDestroyDevice; - PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; - PFN_vkEnumerateDeviceExtensionProperties - vkEnumerateDeviceExtensionProperties; - PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; - PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; - PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; - PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; - // VK_KHR_get_physical_device_properties2 or 1.1.0. - PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; - PFN_vkGetPhysicalDeviceQueueFamilyProperties - vkGetPhysicalDeviceQueueFamilyProperties; - PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR - vkGetPhysicalDeviceSurfaceCapabilitiesKHR; - PFN_vkGetPhysicalDeviceSurfaceFormatsKHR - vkGetPhysicalDeviceSurfaceFormatsKHR; - PFN_vkGetPhysicalDeviceSurfacePresentModesKHR - vkGetPhysicalDeviceSurfacePresentModesKHR; - PFN_vkGetPhysicalDeviceSurfaceSupportKHR - vkGetPhysicalDeviceSurfaceSupportKHR; +#define XE_UI_VULKAN_FUNCTION(name) PFN_##name name; +#define XE_UI_VULKAN_FUNCTION_PROMOTED(extension_name, core_name) \ + PFN_##extension_name extension_name; +#include "xenia/ui/vulkan/functions/instance_1_0.inc" +#include "xenia/ui/vulkan/functions/instance_ext_debug_utils.inc" +#include "xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc" +#include "xenia/ui/vulkan/functions/instance_khr_surface.inc" #if XE_PLATFORM_ANDROID - PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; +#include "xenia/ui/vulkan/functions/instance_khr_android_surface.inc" +#elif XE_PLATFORM_GNU_LINUX +#include "xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc" #elif XE_PLATFORM_WIN32 - PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; +#include "xenia/ui/vulkan/functions/instance_khr_win32_surface.inc" #endif +#undef XE_UI_VULKAN_FUNCTION_PROMOTED +#undef XE_UI_VULKAN_FUNCTION }; const InstanceFunctions& ifn() const { return ifn_; } @@ -120,9 +132,12 @@ class VulkanProvider : public GraphicsProvider { // Core since 1.1.0. bool khr_dedicated_allocation; // Core since 1.2.0. + bool khr_image_format_list; + // Core since 1.2.0. bool khr_shader_float_controls; // Core since 1.2.0. bool khr_spirv_1_4; + bool khr_swapchain; }; const DeviceExtensions& device_extensions() const { return device_extensions_; @@ -139,117 +154,64 @@ class VulkanProvider : public GraphicsProvider { uint32_t memory_types_host_cached() const { return memory_types_host_cached_; } - // FIXME(Triang3l): Allow a separate queue for present - see - // vulkan_provider.cc for details. + struct QueueFamily { + uint32_t queue_first_index = 0; + uint32_t queue_count = 0; + bool potentially_supports_present = false; + }; + const std::vector& queue_families() const { + return queue_families_; + } + // Required. uint32_t queue_family_graphics_compute() const { return queue_family_graphics_compute_; } + // Optional, if sparse binding is supported (UINT32_MAX otherwise). May be the + // same as queue_family_graphics_compute_. + uint32_t queue_family_sparse_binding() const { + return queue_family_sparse_binding_; + } const VkPhysicalDeviceFloatControlsPropertiesKHR& device_float_controls_properties() const { return device_float_controls_properties_; } + struct Queue { + VkQueue queue = VK_NULL_HANDLE; + std::recursive_mutex mutex; + }; + struct QueueAcquisition { + QueueAcquisition(std::unique_lock&& lock, + VkQueue queue) + : lock(std::move(lock)), queue(queue) {} + std::unique_lock lock; + VkQueue queue; + }; + QueueAcquisition AcquireQueue(uint32_t index) { + Queue& queue = queues_[index]; + return QueueAcquisition(std::unique_lock(queue.mutex), + queue.queue); + } + QueueAcquisition AcquireQueue(uint32_t family_index, uint32_t index) { + assert_true(family_index != UINT32_MAX); + return AcquireQueue(queue_families_[family_index].queue_first_index + + index); + } + VkDevice device() const { return device_; } struct DeviceFunctions { - PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; - PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; - PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; - PFN_vkAllocateMemory vkAllocateMemory; - PFN_vkBeginCommandBuffer vkBeginCommandBuffer; - PFN_vkBindBufferMemory vkBindBufferMemory; - PFN_vkBindImageMemory vkBindImageMemory; - PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; - PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets; - PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; - PFN_vkCmdBindPipeline vkCmdBindPipeline; - PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; - PFN_vkCmdClearColorImage vkCmdClearColorImage; - PFN_vkCmdCopyBuffer vkCmdCopyBuffer; - PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; - PFN_vkCmdDraw vkCmdDraw; - PFN_vkCmdDrawIndexed vkCmdDrawIndexed; - PFN_vkCmdEndRenderPass vkCmdEndRenderPass; - PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; - PFN_vkCmdPushConstants vkCmdPushConstants; - PFN_vkCmdSetScissor vkCmdSetScissor; - PFN_vkCmdSetViewport vkCmdSetViewport; - PFN_vkCreateBuffer vkCreateBuffer; - PFN_vkCreateCommandPool vkCreateCommandPool; - PFN_vkCreateDescriptorPool vkCreateDescriptorPool; - PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; - PFN_vkCreateFence vkCreateFence; - PFN_vkCreateFramebuffer vkCreateFramebuffer; - PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; - PFN_vkCreateImage vkCreateImage; - PFN_vkCreateImageView vkCreateImageView; - PFN_vkCreatePipelineLayout vkCreatePipelineLayout; - PFN_vkCreateRenderPass vkCreateRenderPass; - PFN_vkCreateSampler vkCreateSampler; - PFN_vkCreateSemaphore vkCreateSemaphore; - PFN_vkCreateShaderModule vkCreateShaderModule; - PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; - PFN_vkDestroyBuffer vkDestroyBuffer; - PFN_vkDestroyCommandPool vkDestroyCommandPool; - PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool; - PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout; - PFN_vkDestroyFence vkDestroyFence; - PFN_vkDestroyFramebuffer vkDestroyFramebuffer; - PFN_vkDestroyImage vkDestroyImage; - PFN_vkDestroyImageView vkDestroyImageView; - PFN_vkDestroyPipeline vkDestroyPipeline; - PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; - PFN_vkDestroyRenderPass vkDestroyRenderPass; - PFN_vkDestroySampler vkDestroySampler; - PFN_vkDestroySemaphore vkDestroySemaphore; - PFN_vkDestroyShaderModule vkDestroyShaderModule; - PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; - PFN_vkEndCommandBuffer vkEndCommandBuffer; - PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; - PFN_vkFreeMemory vkFreeMemory; - PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; - PFN_vkGetDeviceQueue vkGetDeviceQueue; - PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; - PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; - PFN_vkMapMemory vkMapMemory; - PFN_vkResetCommandPool vkResetCommandPool; - PFN_vkResetDescriptorPool vkResetDescriptorPool; - PFN_vkResetFences vkResetFences; - PFN_vkQueueBindSparse vkQueueBindSparse; - PFN_vkQueuePresentKHR vkQueuePresentKHR; - PFN_vkQueueSubmit vkQueueSubmit; - PFN_vkUnmapMemory vkUnmapMemory; - PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; - PFN_vkWaitForFences vkWaitForFences; +#define XE_UI_VULKAN_FUNCTION(name) PFN_##name name; +#include "xenia/ui/vulkan/functions/device_1_0.inc" +#include "xenia/ui/vulkan/functions/device_khr_swapchain.inc" +#undef XE_UI_VULKAN_FUNCTION }; const DeviceFunctions& dfn() const { return dfn_; } - VkResult SubmitToGraphicsComputeQueue(uint32_t submit_count, - const VkSubmitInfo* submits, - VkFence fence) { - std::lock_guard lock(queue_graphics_compute_mutex_); - return dfn_.vkQueueSubmit(queue_graphics_compute_, submit_count, submits, - fence); - } - // Safer in Xenia context - in case a sparse binding queue was not obtained - // for some reason. + void SetDeviceObjectName(VkObjectType type, uint64_t handle, + const char* name) const; + bool IsSparseBindingSupported() const { - return queue_sparse_binding_ != VK_NULL_HANDLE; - } - VkResult BindSparse(uint32_t bind_info_count, - const VkBindSparseInfo* bind_info, VkFence fence) { - assert_true(IsSparseBindingSupported()); - std::mutex& mutex = queue_sparse_binding_ == queue_graphics_compute_ - ? queue_graphics_compute_mutex_ - : queue_sparse_binding_separate_mutex_; - std::lock_guard lock(mutex); - return dfn_.vkQueueBindSparse(queue_sparse_binding_, bind_info_count, - bind_info, fence); - } - VkResult Present(const VkPresentInfoKHR* present_info) { - // FIXME(Triang3l): Allow a separate queue for present - see - // vulkan_provider.cc for details. - std::lock_guard lock(queue_graphics_compute_mutex_); - return dfn_.vkQueuePresentKHR(queue_graphics_compute_, present_info); + return queue_family_sparse_binding_ != UINT32_MAX; } // Samplers that may be useful for host needs. Only these samplers should be @@ -269,10 +231,26 @@ class VulkanProvider : public GraphicsProvider { } private: - VulkanProvider() = default; + explicit VulkanProvider(bool is_surface_required) + : is_surface_required_(is_surface_required) {} bool Initialize(); + static void AccumulateInstanceExtensions( + size_t properties_count, const VkExtensionProperties* properties, + bool request_debug_utils, InstanceExtensions& instance_extensions, + std::vector& instance_extensions_enabled); + + static VkBool32 VKAPI_CALL DebugMessengerCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_types, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* user_data); + + bool is_surface_required_; + + RenderdocApi renderdoc_api_; + #if XE_PLATFORM_LINUX void* library_ = nullptr; #elif XE_PLATFORM_WIN32 @@ -284,6 +262,8 @@ class VulkanProvider : public GraphicsProvider { InstanceExtensions instance_extensions_; VkInstance instance_ = VK_NULL_HANDLE; InstanceFunctions ifn_; + VkDebugUtilsMessengerEXT debug_messenger_ = VK_NULL_HANDLE; + bool debug_names_used_ = false; VkPhysicalDevice physical_device_ = VK_NULL_HANDLE; VkPhysicalDeviceProperties device_properties_; @@ -293,20 +273,15 @@ class VulkanProvider : public GraphicsProvider { uint32_t memory_types_host_visible_; uint32_t memory_types_host_coherent_; uint32_t memory_types_host_cached_; + std::vector queue_families_; uint32_t queue_family_graphics_compute_; + uint32_t queue_family_sparse_binding_; VkPhysicalDeviceFloatControlsPropertiesKHR device_float_controls_properties_; VkDevice device_ = VK_NULL_HANDLE; DeviceFunctions dfn_ = {}; - VkQueue queue_graphics_compute_; - // VkQueue access must be externally synchronized - must be locked when - // submitting anything. - std::mutex queue_graphics_compute_mutex_; - // May be VK_NULL_HANDLE if not available. - VkQueue queue_sparse_binding_; - // If queue_sparse_binding_ == queue_graphics_compute_, lock - // queue_graphics_compute_mutex_ instead when submitting sparse bindings. - std::mutex queue_sparse_binding_separate_mutex_; + // Queues contain a mutex, can't use std::vector. + std::unique_ptr queues_; VkSampler host_samplers_[size_t(HostSampler::kCount)] = {}; }; diff --git a/src/xenia/ui/vulkan/vulkan_submission_tracker.cc b/src/xenia/ui/vulkan/vulkan_submission_tracker.cc new file mode 100644 index 000000000..f6ebe60bb --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_submission_tracker.cc @@ -0,0 +1,174 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/vulkan/vulkan_submission_tracker.h" + +#include + +#include "xenia/base/assert.h" +#include "xenia/ui/vulkan/vulkan_util.h" + +namespace xe { +namespace ui { +namespace vulkan { + +VulkanSubmissionTracker::FenceAcquisition::~FenceAcquisition() { + if (!submission_tracker_) { + // Dropped submission or left after std::move. + return; + } + assert_true(submission_tracker_->fence_acquired_ == fence_); + if (fence_ != VK_NULL_HANDLE) { + if (signal_failed_) { + // Left in the unsignaled state. + submission_tracker_->fences_reclaimed_.push_back(fence_); + } else { + // Left in the pending state. + submission_tracker_->fences_pending_.emplace_back( + submission_tracker_->submission_current_, fence_); + } + submission_tracker_->fence_acquired_ = VK_NULL_HANDLE; + } + ++submission_tracker_->submission_current_; +} + +void VulkanSubmissionTracker::Shutdown() { + AwaitAllSubmissionsCompletion(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + for (VkFence fence : fences_reclaimed_) { + dfn.vkDestroyFence(device, fence, nullptr); + } + fences_reclaimed_.clear(); + for (const std::pair& fence_pair : fences_pending_) { + dfn.vkDestroyFence(device, fence_pair.second, nullptr); + } + fences_pending_.clear(); + assert_true(fence_acquired_ == VK_NULL_HANDLE); + util::DestroyAndNullHandle(dfn.vkDestroyFence, device, fence_acquired_); +} + +void VulkanSubmissionTracker::FenceAcquisition::SubmissionFailedOrDropped() { + if (!submission_tracker_) { + return; + } + assert_true(submission_tracker_->fence_acquired_ == fence_); + if (fence_ != VK_NULL_HANDLE) { + submission_tracker_->fences_reclaimed_.push_back(fence_); + } + submission_tracker_->fence_acquired_ = VK_NULL_HANDLE; + fence_ = VK_NULL_HANDLE; + // No submission acquisition from now on, don't increment the current + // submission index as well. + submission_tracker_ = VK_NULL_HANDLE; +} + +uint64_t VulkanSubmissionTracker::UpdateAndGetCompletedSubmission() { + if (!fences_pending_.empty()) { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + while (!fences_pending_.empty()) { + const std::pair& pending_pair = + fences_pending_.front(); + assert_true(pending_pair.first > submission_completed_on_gpu_); + if (dfn.vkGetFenceStatus(device, pending_pair.second) != VK_SUCCESS) { + break; + } + fences_reclaimed_.push_back(pending_pair.second); + submission_completed_on_gpu_ = pending_pair.first; + fences_pending_.pop_front(); + } + } + return submission_completed_on_gpu_; +} + +bool VulkanSubmissionTracker::AwaitSubmissionCompletion( + uint64_t submission_index) { + // The tracker itself can't give a submission index for a submission that + // hasn't even started being recorded yet, the client has provided a + // completely invalid value or has done overly optimistic math if such an + // index has been obtained somehow. + assert_true(submission_index <= submission_current_); + // Waiting for the current submission is fine if there was a failure or a + // refusal to submit, and the submission index wasn't incremented, but still + // need to release objects referenced in the dropped submission (while + // shutting down, for instance - in this case, waiting for the last successful + // submission, which could have also referenced the objects from the new + // submission - we can't know since the client has already overwritten its + // last usage index, would correctly ensure that GPU usage of the objects is + // not pending). Waiting for successful submissions, but failed signals, will + // result in a true race condition, however, but waiting for the closest + // successful signal is the best approximation - also retrying to signal in + // this case. + // Go from the most recent to wait only for one fence, which includes all the + // preceding ones. + // "Fence signal operations that are defined by vkQueueSubmit additionally + // include in the first synchronization scope all commands that occur earlier + // in submission order." + size_t reclaim_end = fences_pending_.size(); + if (reclaim_end) { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + while (reclaim_end) { + const std::pair& pending_pair = + fences_pending_[reclaim_end - 1]; + assert_true(pending_pair.first > submission_completed_on_gpu_); + if (pending_pair.first <= submission_index) { + // Wait if requested. + if (dfn.vkWaitForFences(device, 1, &pending_pair.second, VK_TRUE, + UINT64_MAX) == VK_SUCCESS) { + break; + } + } + // Just refresh the completed submission. + if (dfn.vkGetFenceStatus(device, pending_pair.second) == VK_SUCCESS) { + break; + } + --reclaim_end; + } + if (reclaim_end) { + submission_completed_on_gpu_ = fences_pending_[reclaim_end - 1].first; + for (; reclaim_end; --reclaim_end) { + fences_reclaimed_.push_back(fences_pending_.front().second); + fences_pending_.pop_front(); + } + } + } + return submission_completed_on_gpu_ == submission_index; +} + +VulkanSubmissionTracker::FenceAcquisition +VulkanSubmissionTracker::AcquireFenceToAdvanceSubmission() { + assert_true(fence_acquired_ == VK_NULL_HANDLE); + // Reclaim fences if the client only gets the completed submission index or + // awaits in special cases such as shutdown. + UpdateAndGetCompletedSubmission(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + if (!fences_reclaimed_.empty()) { + VkFence reclaimed_fence = fences_reclaimed_.back(); + if (dfn.vkResetFences(device, 1, &reclaimed_fence) == VK_SUCCESS) { + fence_acquired_ = fences_reclaimed_.back(); + fences_reclaimed_.pop_back(); + } + } + if (fence_acquired_ == VK_NULL_HANDLE) { + VkFenceCreateInfo fence_create_info; + fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_create_info.pNext = nullptr; + fence_create_info.flags = 0; + // May fail, a null fence is handled in FenceAcquisition. + dfn.vkCreateFence(device, &fence_create_info, nullptr, &fence_acquired_); + } + return FenceAcquisition(*this, fence_acquired_); +} + +} // namespace vulkan +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_submission_tracker.h b/src/xenia/ui/vulkan/vulkan_submission_tracker.h new file mode 100644 index 000000000..c1f055c87 --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_submission_tracker.h @@ -0,0 +1,135 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_VULKAN_VULKAN_SUBMISSION_TRACKER_H_ +#define XENIA_UI_VULKAN_VULKAN_SUBMISSION_TRACKER_H_ + +#include +#include +#include +#include + +#include "xenia/ui/vulkan/vulkan_provider.h" + +namespace xe { +namespace ui { +namespace vulkan { + +// Fence wrapper, safely handling cases when the fence has not been initialized +// yet or has already been shut down, and failed or dropped submissions. +// +// The current submission index can be associated with the usage of objects to +// release them when the GPU isn't potentially referencing them anymore, and +// should be incremented only +// +// 0 can be used as a "never referenced" submission index. +// +// The submission index timeline survives Shutdown, so submission indices can be +// given to clients that are not aware of the lifetime of the tracker. +// +// To transfer the tracker to another queue (to make sure the first signal on +// the new queue does not happen before the last signal on the old one), call +// AwaitAllSubmissionsCompletion before doing the first submission on the new +// one. +class VulkanSubmissionTracker { + public: + class FenceAcquisition { + public: + FenceAcquisition() : submission_tracker_(nullptr), fence_(VK_NULL_HANDLE) {} + FenceAcquisition(VulkanSubmissionTracker& submission_tracker, VkFence fence) + : submission_tracker_(&submission_tracker), fence_(fence) {} + FenceAcquisition(const FenceAcquisition& fence_acquisition) = delete; + FenceAcquisition& operator=(const FenceAcquisition& fence_acquisition) = + delete; + FenceAcquisition(FenceAcquisition&& fence_acquisition) { + *this = std::move(fence_acquisition); + } + FenceAcquisition& operator=(FenceAcquisition&& fence_acquisition) { + if (this == &fence_acquisition) { + return *this; + } + submission_tracker_ = fence_acquisition.submission_tracker_; + fence_acquisition.submission_tracker_ = nullptr; + fence_ = fence_acquisition.fence_; + fence_acquisition.fence_ = VK_NULL_HANDLE; + return *this; + } + ~FenceAcquisition(); + + // In unsignaled state. May be null if failed to create or to reset a fence. + VkFence fence() { return fence_; } + + // Call if vkQueueSubmit has failed (or it was decided not to commit the + // submission), and the submission index shouldn't be incremented by + // releasing this submission (for instance, to retry commands with long-term + // effects like copying or image layout changes later if in the attempt the + // submission index stays the same). + void SubmissionFailedOrDropped(); + // Call if for some reason (like signaling multiple fences) the fence + // signaling was done in a separate submission than the command buffer, and + // the command buffer vkQueueSubmit succeeded (so commands with long-term + // effects will be executed), but the fence-only vkQueueSubmit has failed, + // thus the tracker shouldn't attempt to wait for that fence (it will be in + // the unsignaled state). + void SubmissionSucceededSignalFailed() { signal_failed_ = true; } + + private: + // If nullptr, has been moved to another FenceAcquisition - not holding a + // fence from now on. + VulkanSubmissionTracker* submission_tracker_; + VkFence fence_; + bool signal_failed_ = false; + }; + + VulkanSubmissionTracker(VulkanProvider& provider) : provider_(provider) {} + VulkanSubmissionTracker(const VulkanSubmissionTracker& submission_tracker) = + delete; + VulkanSubmissionTracker& operator=( + const VulkanSubmissionTracker& submission_tracker) = delete; + ~VulkanSubmissionTracker() { Shutdown(); } + + void Shutdown(); + + uint64_t GetCurrentSubmission() const { return submission_current_; } + uint64_t UpdateAndGetCompletedSubmission(); + + // Returns whether the expected GPU signal has actually been reached (rather + // than some fallback condition) for cases when stronger completeness + // guarantees as needed (when downloading, as opposed to just destroying). + // If false is returned, it's also not guaranteed that GetCompletedSubmission + // will return a value >= submission_index. + bool AwaitSubmissionCompletion(uint64_t submission_index); + bool AwaitAllSubmissionsCompletion() { + return AwaitSubmissionCompletion(submission_current_ - 1); + } + + [[nodiscard]] FenceAcquisition AcquireFenceToAdvanceSubmission(); + + private: + VulkanProvider& provider_; + uint64_t submission_current_ = 1; + // Last submission with a successful fence signal as well as a successful + // fence wait / query. + uint64_t submission_completed_on_gpu_ = 0; + // The flow is: + // Reclaimed (or create if empty) > acquired > pending > reclaimed. + // Or, if dropped the submission while acquired: + // Reclaimed (or create if empty) > acquired > reclaimed. + VkFence fence_acquired_ = VK_NULL_HANDLE; + // Ordered by the submission index (the first pair member). + std::deque> fences_pending_; + // Fences are reclaimed when awaiting or when refreshing the completed value. + std::vector fences_reclaimed_; +}; + +} // namespace vulkan +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_VULKAN_VULKAN_SUBMISSION_TRACKER_H_ diff --git a/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.cc b/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.cc index 1c71db6ea..2e0a054c7 100644 --- a/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.cc +++ b/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.cc @@ -19,8 +19,11 @@ namespace xe { namespace ui { namespace vulkan { -// Memory mappings are always aligned to nonCoherentAtomSize, so for simplicity, -// round the page size to it now via GetMappableMemorySize. +// Host-visible memory sizes are likely to be internally rounded to +// nonCoherentAtomSize (it's the memory mapping granularity, though as the map +// or flush range must be clamped to the actual allocation size as a special +// case, but it's still unlikely that the allocation won't be aligned to it), so +// try not to waste that padding. VulkanUploadBufferPool::VulkanUploadBufferPool(const VulkanProvider& provider, VkBufferUsageFlags usage, size_t page_size) @@ -72,8 +75,6 @@ VulkanUploadBufferPool::CreatePageImplementation() { const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); VkDevice device = provider_.device(); - // For the first call, the page size is already aligned to nonCoherentAtomSize - // for mapping. VkBufferCreateInfo buffer_create_info; buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_create_info.pNext = nullptr; @@ -105,16 +106,10 @@ VulkanUploadBufferPool::CreatePageImplementation() { return nullptr; } allocation_size_ = memory_requirements.size; - // On some Android implementations, nonCoherentAtomSize is 0, not 1. - VkDeviceSize non_coherent_atom_size = - std::max(provider_.device_properties().limits.nonCoherentAtomSize, - VkDeviceSize(1)); - VkDeviceSize allocation_size_aligned = - allocation_size_ / non_coherent_atom_size * non_coherent_atom_size; - if (allocation_size_aligned > page_size_) { - // Try to occupy all the allocation padding. If that's going to require - // even more memory for some reason, don't. - buffer_create_info.size = allocation_size_aligned; + if (allocation_size_ > page_size_) { + // Try to occupy the allocation padding. If that's going to require even + // more memory for some reason, don't. + buffer_create_info.size = allocation_size_; VkBuffer buffer_expanded; if (dfn.vkCreateBuffer(device, &buffer_create_info, nullptr, &buffer_expanded) == VK_SUCCESS) { @@ -125,8 +120,7 @@ VulkanUploadBufferPool::CreatePageImplementation() { provider_, memory_requirements.memoryTypeBits, false); if (memory_requirements_expanded.size <= allocation_size_ && memory_type_expanded != UINT32_MAX) { - // page_size_ must be aligned to nonCoherentAtomSize. - page_size_ = size_t(allocation_size_aligned); + page_size_ = size_t(allocation_size_); allocation_size_ = memory_requirements_expanded.size; memory_type_ = memory_type_expanded; dfn.vkDestroyBuffer(device, buffer, nullptr); @@ -139,20 +133,22 @@ VulkanUploadBufferPool::CreatePageImplementation() { } VkMemoryAllocateInfo memory_allocate_info; + VkMemoryAllocateInfo* memory_allocate_info_last = &memory_allocate_info; memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = nullptr; + memory_allocate_info.allocationSize = allocation_size_; + memory_allocate_info.memoryTypeIndex = memory_type_; VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info; if (provider_.device_extensions().khr_dedicated_allocation) { + memory_allocate_info_last->pNext = &memory_dedicated_allocate_info; + memory_allocate_info_last = reinterpret_cast( + &memory_dedicated_allocate_info); memory_dedicated_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; memory_dedicated_allocate_info.pNext = nullptr; memory_dedicated_allocate_info.image = VK_NULL_HANDLE; memory_dedicated_allocate_info.buffer = buffer; - memory_allocate_info.pNext = &memory_dedicated_allocate_info; - } else { - memory_allocate_info.pNext = nullptr; } - memory_allocate_info.allocationSize = allocation_size_; - memory_allocate_info.memoryTypeIndex = memory_type_; VkDeviceMemory memory; if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) != VK_SUCCESS) { @@ -171,10 +167,10 @@ VulkanUploadBufferPool::CreatePageImplementation() { } void* mapping; - // page_size_ is aligned to nonCoherentAtomSize. - if (dfn.vkMapMemory(device, memory, 0, page_size_, 0, &mapping) != + if (dfn.vkMapMemory(device, memory, 0, VK_WHOLE_SIZE, 0, &mapping) != VK_SUCCESS) { - XELOGE("Failed to map {} bytes of Vulkan upload buffer memory", page_size_); + XELOGE("Failed to map {} bytes of Vulkan upload buffer memory", + allocation_size_); dfn.vkDestroyBuffer(device, buffer, nullptr); dfn.vkFreeMemory(device, memory, nullptr); return nullptr; @@ -187,7 +183,7 @@ void VulkanUploadBufferPool::FlushPageWrites(Page* page, size_t offset, size_t size) { util::FlushMappedMemoryRange( provider_, static_cast(page)->memory_, memory_type_, - VkDeviceSize(offset), VkDeviceSize(size)); + VkDeviceSize(offset), allocation_size_, VkDeviceSize(size)); } VulkanUploadBufferPool::VulkanPage::~VulkanPage() { diff --git a/src/xenia/ui/vulkan/vulkan_util.cc b/src/xenia/ui/vulkan/vulkan_util.cc index 49d8a949c..f8dd5846e 100644 --- a/src/xenia/ui/vulkan/vulkan_util.cc +++ b/src/xenia/ui/vulkan/vulkan_util.cc @@ -22,7 +22,11 @@ namespace util { void FlushMappedMemoryRange(const VulkanProvider& provider, VkDeviceMemory memory, uint32_t memory_type, - VkDeviceSize offset, VkDeviceSize size) { + VkDeviceSize offset, VkDeviceSize memory_size, + VkDeviceSize size) { + assert_false(size != VK_WHOLE_SIZE && memory_size == VK_WHOLE_SIZE); + assert_true(memory_size == VK_WHOLE_SIZE || offset <= memory_size); + assert_true(memory_size == VK_WHOLE_SIZE || size <= memory_size - offset); if (!size || (provider.memory_types_host_coherent() & (uint32_t(1) << memory_type))) { return; @@ -39,8 +43,9 @@ void FlushMappedMemoryRange(const VulkanProvider& provider, if (non_coherent_atom_size > 1) { range.offset = offset / non_coherent_atom_size * non_coherent_atom_size; if (size != VK_WHOLE_SIZE) { - range.size = - xe::round_up(offset + size, non_coherent_atom_size) - range.offset; + range.size = std::min(xe::round_up(offset + size, non_coherent_atom_size), + memory_size) - + range.offset; } } provider.dfn().vkFlushMappedMemoryRanges(provider.device(), 1, &range); @@ -49,7 +54,8 @@ void FlushMappedMemoryRange(const VulkanProvider& provider, bool CreateDedicatedAllocationBuffer( const VulkanProvider& provider, VkDeviceSize size, VkBufferUsageFlags usage, MemoryPurpose memory_purpose, VkBuffer& buffer_out, - VkDeviceMemory& memory_out, uint32_t* memory_type_out) { + VkDeviceMemory& memory_out, uint32_t* memory_type_out, + VkDeviceSize* memory_size_out) { const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkDevice device = provider.device(); @@ -70,55 +76,37 @@ bool CreateDedicatedAllocationBuffer( VkMemoryRequirements memory_requirements; dfn.vkGetBufferMemoryRequirements(device, buffer, &memory_requirements); - uint32_t memory_type = UINT32_MAX; - switch (memory_purpose) { - case MemoryPurpose::kDeviceLocal: - if (!xe::bit_scan_forward(memory_requirements.memoryTypeBits & - provider.memory_types_device_local(), - &memory_type)) { - memory_type = UINT32_MAX; - } - break; - case MemoryPurpose::kUpload: - case MemoryPurpose::kReadback: - memory_type = - ChooseHostMemoryType(provider, memory_requirements.memoryTypeBits, - memory_purpose == MemoryPurpose::kReadback); - break; - default: - assert_unhandled_case(memory_purpose); - } + uint32_t memory_type = ChooseMemoryType( + provider, memory_requirements.memoryTypeBits, memory_purpose); if (memory_type == UINT32_MAX) { dfn.vkDestroyBuffer(device, buffer, nullptr); return false; } VkMemoryAllocateInfo memory_allocate_info; + VkMemoryAllocateInfo* memory_allocate_info_last = &memory_allocate_info; memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = nullptr; + memory_allocate_info.allocationSize = memory_requirements.size; + memory_allocate_info.memoryTypeIndex = memory_type; VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info; if (provider.device_extensions().khr_dedicated_allocation) { + memory_allocate_info_last->pNext = &memory_dedicated_allocate_info; + memory_allocate_info_last = reinterpret_cast( + &memory_dedicated_allocate_info); memory_dedicated_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; memory_dedicated_allocate_info.pNext = nullptr; memory_dedicated_allocate_info.image = VK_NULL_HANDLE; memory_dedicated_allocate_info.buffer = buffer; - memory_allocate_info.pNext = &memory_dedicated_allocate_info; - } else { - memory_allocate_info.pNext = nullptr; } - memory_allocate_info.allocationSize = memory_requirements.size; - if (memory_purpose == MemoryPurpose::kUpload || - memory_purpose == MemoryPurpose::kReadback) { - memory_allocate_info.allocationSize = - GetMappableMemorySize(provider, memory_allocate_info.allocationSize); - } - memory_allocate_info.memoryTypeIndex = memory_type; VkDeviceMemory memory; if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) != VK_SUCCESS) { dfn.vkDestroyBuffer(device, buffer, nullptr); return false; } + if (dfn.vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) { dfn.vkDestroyBuffer(device, buffer, nullptr); dfn.vkFreeMemory(device, memory, nullptr); @@ -130,6 +118,74 @@ bool CreateDedicatedAllocationBuffer( if (memory_type_out) { *memory_type_out = memory_type; } + if (memory_size_out) { + *memory_size_out = memory_allocate_info.allocationSize; + } + return true; +} + +bool CreateDedicatedAllocationImage(const VulkanProvider& provider, + const VkImageCreateInfo& create_info, + MemoryPurpose memory_purpose, + VkImage& image_out, + VkDeviceMemory& memory_out, + uint32_t* memory_type_out, + VkDeviceSize* memory_size_out) { + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + + VkImage image; + if (dfn.vkCreateImage(device, &create_info, nullptr, &image) != VK_SUCCESS) { + return false; + } + + VkMemoryRequirements memory_requirements; + dfn.vkGetImageMemoryRequirements(device, image, &memory_requirements); + uint32_t memory_type = ChooseMemoryType( + provider, memory_requirements.memoryTypeBits, memory_purpose); + if (memory_type == UINT32_MAX) { + dfn.vkDestroyImage(device, image, nullptr); + return false; + } + + VkMemoryAllocateInfo memory_allocate_info; + VkMemoryAllocateInfo* memory_allocate_info_last = &memory_allocate_info; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = nullptr; + memory_allocate_info.allocationSize = memory_requirements.size; + memory_allocate_info.memoryTypeIndex = memory_type; + VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info; + if (provider.device_extensions().khr_dedicated_allocation) { + memory_allocate_info_last->pNext = &memory_dedicated_allocate_info; + memory_allocate_info_last = reinterpret_cast( + &memory_dedicated_allocate_info); + memory_dedicated_allocate_info.sType = + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; + memory_dedicated_allocate_info.pNext = nullptr; + memory_dedicated_allocate_info.image = image; + memory_dedicated_allocate_info.buffer = VK_NULL_HANDLE; + } + VkDeviceMemory memory; + if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) != + VK_SUCCESS) { + dfn.vkDestroyImage(device, image, nullptr); + return false; + } + + if (dfn.vkBindImageMemory(device, image, memory, 0) != VK_SUCCESS) { + dfn.vkDestroyImage(device, image, nullptr); + dfn.vkFreeMemory(device, memory, nullptr); + return false; + } + + image_out = image; + memory_out = memory; + if (memory_type_out) { + *memory_type_out = memory_type; + } + if (memory_size_out) { + *memory_size_out = memory_allocate_info.allocationSize; + } return true; } diff --git a/src/xenia/ui/vulkan/vulkan_util.h b/src/xenia/ui/vulkan/vulkan_util.h index 163731699..85fc17717 100644 --- a/src/xenia/ui/vulkan/vulkan_util.h +++ b/src/xenia/ui/vulkan/vulkan_util.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_UI_VULKAN_VULKAN_UTIL_H_ #define XENIA_UI_VULKAN_VULKAN_UTIL_H_ +#include #include #include "xenia/base/math.h" @@ -75,11 +76,46 @@ inline uint32_t ChooseHostMemoryType(const VulkanProvider& provider, return UINT32_MAX; } +inline uint32_t ChooseMemoryType(const VulkanProvider& provider, + uint32_t supported_types, + MemoryPurpose purpose) { + switch (purpose) { + case MemoryPurpose::kDeviceLocal: { + uint32_t memory_type; + return xe::bit_scan_forward(supported_types, &memory_type) ? memory_type + : UINT32_MAX; + } break; + case MemoryPurpose::kUpload: + case MemoryPurpose::kReadback: + return ChooseHostMemoryType(provider, supported_types, + purpose == MemoryPurpose::kReadback); + default: + assert_unhandled_case(purpose); + return UINT32_MAX; + } +} + +// Actual memory size is required if explicit size is specified for clamping to +// the actual memory allocation size while rounding to the non-coherent atom +// size (offset + size passed to vkFlushMappedMemoryRanges inside this function +// must be either a multiple of nonCoherentAtomSize (but not exceeding the +// memory size) or equal to the memory size). void FlushMappedMemoryRange(const VulkanProvider& provider, VkDeviceMemory memory, uint32_t memory_type, VkDeviceSize offset = 0, + VkDeviceSize memory_size = VK_WHOLE_SIZE, VkDeviceSize size = VK_WHOLE_SIZE); +inline VkExtent2D GetMax2DFramebufferExtent(const VulkanProvider& provider) { + const VkPhysicalDeviceLimits& limits = provider.device_properties().limits; + VkExtent2D max_extent; + max_extent.width = + std::min(limits.maxFramebufferWidth, limits.maxImageDimension2D); + max_extent.height = + std::min(limits.maxFramebufferHeight, limits.maxImageDimension2D); + return max_extent; +} + inline void InitializeSubresourceRange( VkImageSubresourceRange& range, VkImageAspectFlags aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -93,13 +129,22 @@ inline void InitializeSubresourceRange( range.layerCount = layer_count; } -// Creates a buffer backed by a dedicated allocation. If using a mappable memory -// purpose (upload/readback), the allocation size will be aligned to -// nonCoherentAtomSize. +// Creates a buffer backed by a dedicated allocation. The allocation size will +// NOT be aligned to nonCoherentAtomSize - if mapping or flushing not the whole +// size, memory_size_out must be used for clamping the range. bool CreateDedicatedAllocationBuffer( const VulkanProvider& provider, VkDeviceSize size, VkBufferUsageFlags usage, MemoryPurpose memory_purpose, VkBuffer& buffer_out, - VkDeviceMemory& memory_out, uint32_t* memory_type_out = nullptr); + VkDeviceMemory& memory_out, uint32_t* memory_type_out = nullptr, + VkDeviceSize* memory_size_out = nullptr); + +bool CreateDedicatedAllocationImage(const VulkanProvider& provider, + const VkImageCreateInfo& create_info, + MemoryPurpose memory_purpose, + VkImage& image_out, + VkDeviceMemory& memory_out, + uint32_t* memory_type_out = nullptr, + VkDeviceSize* memory_size_out = nullptr); inline VkShaderModule CreateShaderModule(const VulkanProvider& provider, const void* code, size_t code_size) { @@ -114,7 +159,7 @@ inline VkShaderModule CreateShaderModule(const VulkanProvider& provider, provider.device(), &shader_module_create_info, nullptr, &shader_module) == VK_SUCCESS ? shader_module - : nullptr; + : VK_NULL_HANDLE; } } // namespace util diff --git a/src/xenia/ui/vulkan/vulkan_window_demo.cc b/src/xenia/ui/vulkan/vulkan_window_demo.cc index f2e0fcff8..f4ba6a669 100644 --- a/src/xenia/ui/vulkan/vulkan_window_demo.cc +++ b/src/xenia/ui/vulkan/vulkan_window_demo.cc @@ -34,7 +34,7 @@ class VulkanWindowDemoApp final : public WindowDemoApp { std::unique_ptr VulkanWindowDemoApp::CreateGraphicsProvider() const { - return VulkanProvider::Create(); + return VulkanProvider::Create(true); } } // namespace vulkan diff --git a/src/xenia/ui/window.cc b/src/xenia/ui/window.cc index 74b81ae21..ad6129307 100644 --- a/src/xenia/ui/window.cc +++ b/src/xenia/ui/window.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,347 +10,719 @@ #include "xenia/ui/window.h" #include +#include #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" #include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/presenter.h" namespace xe { namespace ui { -constexpr bool kContinuousRepaint = false; -constexpr bool kShowPresentFps = kContinuousRepaint; - -// Enables long press behaviors (context menu, etc). -constexpr bool kTouch = false; - -constexpr uint64_t kDoubleClickDelayMillis = 600; -constexpr double kDoubleClickDistance = 5; - -constexpr int32_t kMouseWheelDetent = 120; - -Window::Window(WindowedAppContext& app_context, const std::string& title) - : app_context_(app_context), title_(title) {} +Window::Window(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height) + : app_context_(app_context), + title_(title), + desired_logical_width_(desired_logical_width), + desired_logical_height_(desired_logical_height) {} Window::~Window() { - // Context must have been cleaned up already in OnDestroy. - assert_null(context_.get()); + // In case the implementation didn't need to call EnterDestructor. Though + // that was likely a mistake, so placing an assertion. + assert_true(phase_ == Phase::kDeleting); + EnterDestructor(); + + if (presenter_) { + Presenter* old_presenter = presenter_; + // Null the pointer to prevent an infinite loop between + // SetWindowSurfaceFromUIThread and SetPresenter calling each other. + presenter_ = nullptr; + old_presenter->SetWindowSurfaceFromUIThread(nullptr, nullptr); + presenter_surface_.reset(); + } + + // Right before destruction has finished, after which no interaction with + // *this can be done, notify the destruction receivers that the window is + // being destroyed and that *this is not accessible anymore. + while (innermost_destruction_receiver_) { + innermost_destruction_receiver_->window_ = nullptr; + innermost_destruction_receiver_ = + innermost_destruction_receiver_->outer_receiver_; + } } -void Window::AttachListener(WindowListener* listener) { - if (in_listener_loop_) { - pending_listener_attaches_.push_back(listener); - return; - } - auto it = std::find(listeners_.begin(), listeners_.end(), listener); - if (it != listeners_.end()) { +void Window::AddListener(WindowListener* listener) { + assert_not_null(listener); + // Check if already added. + if (std::find(listeners_.cbegin(), listeners_.cend(), listener) != + listeners_.cend()) { return; } listeners_.push_back(listener); - Invalidate(); } -void Window::DetachListener(WindowListener* listener) { - if (in_listener_loop_) { - pending_listener_detaches_.push_back(listener); +void Window::RemoveListener(WindowListener* listener) { + assert_not_null(listener); + auto it = std::find(listeners_.cbegin(), listeners_.cend(), listener); + if (it == listeners_.cend()) { return; } - auto it = std::find(listeners_.begin(), listeners_.end(), listener); - if (it == listeners_.end()) { - return; + // Actualize the next listener indices after the erasure from the vector. + ListenerIterationContext* iteration_context = + innermost_listener_iteration_context_; + if (iteration_context) { + size_t existing_index = size_t(std::distance(listeners_.cbegin(), it)); + while (iteration_context) { + if (iteration_context->next_index > existing_index) { + --iteration_context->next_index; + } + iteration_context = iteration_context->outer_context; + } } listeners_.erase(it); } -void Window::ForEachListener(std::function fn) { - assert_false(in_listener_loop_); - in_listener_loop_ = true; - for (auto listener : listeners_) { - fn(listener); +void Window::AddInputListener(WindowInputListener* listener, size_t z_order) { + assert_not_null(listener); + // Check if already added. + for (auto it_existing = input_listeners_.rbegin(); + it_existing != input_listeners_.rend(); ++it_existing) { + if (it_existing->second != listener) { + continue; + } + if (it_existing->first == z_order) { + return; + } + // If removing the listener that is the next in a current listener loop, + // skip it (in a multimap, only one element iterator is invalidated). + InputListenerIterationContext* iteration_context = + innermost_input_listener_iteration_context_; + while (iteration_context) { + if (iteration_context->next_iterator == it_existing) { + ++iteration_context->next_iterator; + } + iteration_context = iteration_context->outer_context; + } + input_listeners_.erase(std::prev(it_existing.base())); + // FIXME(Triang3l): Changing the Z order of an existing listener while + // already executing the listeners may cause listeners to be called twice if + // the Z order is lowered from one that has already been processed to one + // below the current one. Because nested listener calls are supported, a + // single last call index can't be associated with a listener to skip it if + // calling twice for the same event (a "not equal to" comparison of the call + // indices will result in the skipping being cancelled in the outer loop if + // an inner one is done, a "greater than" comparison will cause the inner + // loop to effectively terminate all outer ones). } - in_listener_loop_ = false; - while (!pending_listener_attaches_.empty()) { - auto listener = pending_listener_attaches_.back(); - pending_listener_attaches_.pop_back(); - AttachListener(listener); - } - while (!pending_listener_detaches_.empty()) { - auto listener = pending_listener_detaches_.back(); - pending_listener_detaches_.pop_back(); - DetachListener(listener); - } -} - -void Window::TryForEachListener(std::function fn) { - assert_false(in_listener_loop_); - in_listener_loop_ = true; - for (auto listener : listeners_) { - if (fn(listener)) { - break; + auto it_new = std::prev( + std::make_reverse_iterator(input_listeners_.emplace(z_order, listener))); + // If adding to layers in between the currently being processed ones (from + // highest to lowest) and the previously next, make sure the new listener is + // executed too. Execution within one layer, however, happens in the reverse + // order of addition, so if adding to the Z layer currently being processed, + // the new listener must not be executed within the loop. But, if adding to + // the next Z layer after the current one, it must be executed immediately. + { + InputListenerIterationContext* iteration_context = + innermost_input_listener_iteration_context_; + while (iteration_context) { + if (z_order < iteration_context->current_z_order && + (iteration_context->next_iterator == input_listeners_.crend() || + z_order >= iteration_context->next_iterator->first)) { + iteration_context->next_iterator = it_new; + } + iteration_context = iteration_context->outer_context; } } - in_listener_loop_ = false; - while (!pending_listener_attaches_.empty()) { - auto listener = pending_listener_attaches_.back(); - pending_listener_attaches_.pop_back(); - AttachListener(listener); - } - while (!pending_listener_detaches_.empty()) { - auto listener = pending_listener_detaches_.back(); - pending_listener_detaches_.pop_back(); - DetachListener(listener); - } } -void Window::set_imgui_input_enabled(bool value) { - if (value == is_imgui_input_enabled_) { +void Window::RemoveInputListener(WindowInputListener* listener) { + assert_not_null(listener); + for (auto it_existing = input_listeners_.rbegin(); + it_existing != input_listeners_.rend(); ++it_existing) { + if (it_existing->second != listener) { + continue; + } + // If removing the listener that is the next in a current listener loop, + // skip it (in a multimap, only one element iterator is invalidated). + InputListenerIterationContext* iteration_context = + innermost_input_listener_iteration_context_; + while (iteration_context) { + if (iteration_context->next_iterator == it_existing) { + ++iteration_context->next_iterator; + } + iteration_context = iteration_context->outer_context; + } + input_listeners_.erase(std::prev(it_existing.base())); return; } - is_imgui_input_enabled_ = value; - if (!value) { - DetachListener(imgui_drawer_.get()); - } else { - AttachListener(imgui_drawer_.get()); - } } -bool Window::OnCreate() { return true; } +bool Window::Open() { + if (phase_ != Phase::kClosedOpenable) { + return true; + } -bool Window::MakeReady() { - imgui_drawer_ = std::make_unique(this); + // For consistency of the behavior of OpenImpl and the initial On*Update + // that should be called as a result of it, reset the actual state to its + // defaults for a closed window. + // Note that this is performed in Open, not after closing, because there's + // only one entry point for opening a window, while closing may be done + // different ways - by actually closing, by destroying, or by failing to call + // OpenImpl - instead of performing this reset in every possible close case, + // just returning these defaults from the actual state getters if + // HasActualState is false. + actual_physical_width_ = 0; + actual_physical_height_ = 0; + has_focus_ = false; + phase_ = Phase::kOpening; + bool platform_open_result = OpenImpl(); + if (!platform_open_result) { + phase_ = Phase::kClosedOpenable; + return false; + } + if (phase_ != Phase::kOpening) { + // The window was closed mid-opening. + return true; + } + phase_ = Phase::kOpen; + + // Call the listeners (OnOpened with all the new state so the listeners are + // aware that they can start interacting with the open Window, and after that, + // in case certain listeners don't handle OnOpened, but rather, only need the + // more granular callbacks, make sure those callbacks receive the new state + // too) for the actual state of the new window (that may be different than the + // desired, depending on how the platform has interpreted the desired state). + { + MonitorUpdateEvent e(this, true, true); + OnMonitorUpdate(e); + } + { + UISetupEvent e(this, true); + WindowDestructionReceiver destruction_receiver(this); + SendEventToListeners([&e](auto listener) { listener->OnOpened(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrListenersUncallable()) { + return true; + } + SendEventToListeners([&e](auto listener) { listener->OnDpiChanged(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrListenersUncallable()) { + return true; + } + SendEventToListeners([&e](auto listener) { listener->OnResize(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrListenersUncallable()) { + return true; + } + if (HasFocus()) { + SendEventToListeners([&e](auto listener) { listener->OnGotFocus(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrListenersUncallable()) { + return true; + } + } + } + + // May now try to create a valid surface (though the window may be in a + // minimized state without the possibility of creating a surface, but that + // will be resolved by the implementation), after OnDpiChanged and OnResize so + // nothing related to painting will be making wrong assumptions about the + // size. + OnSurfaceChanged(true); return true; } -void Window::OnMainMenuChange() { - ForEachListener([](auto listener) { listener->OnMainMenuChange(); }); +void Window::SetFullscreen(bool new_fullscreen) { + if (fullscreen_ == new_fullscreen) { + return; + } + fullscreen_ = new_fullscreen; + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewFullscreen(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } } -void Window::OnClose() { - UIEvent e(this); - ForEachListener([&e](auto listener) { listener->OnClosing(&e); }); - on_closing(&e); - ForEachListener([&e](auto listener) { listener->OnClosed(&e); }); - on_closed(&e); +void Window::SetTitle(const std::string_view new_title) { + if (title_ == new_title) { + return; + } + title_ = new_title; + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewTitle(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } } -void Window::OnDestroy() { - if (!context_) { +void Window::SetIcon(const void* buffer, size_t size) { + bool reset = !buffer || !size; + WindowDestructionReceiver destruction_receiver(this); + LoadAndApplyIcon(reset ? nullptr : buffer, reset ? 0 : size, CanApplyState()); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::SetMainMenu(std::unique_ptr new_main_menu) { + // The primary reason for this comparison (of two unique pointers) is + // nullptr == nullptr. + if (main_menu_ == new_main_menu) { + return; + } + // Keep the old menu object existing while it's still being detached from + // the platform window. + std::unique_ptr old_main_menu = std::move(main_menu_); + main_menu_ = std::move(new_main_menu); + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewMainMenu(old_main_menu.get()); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::CompleteMainMenuItemsUpdate() { + if (!main_menu_ || !CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + CompleteMainMenuItemsUpdateImpl(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::SetMainMenuEnabled(bool enabled) { + if (!main_menu_) { + return; + } + // Not comparing to the actual enabled state, it's a part of the MenuItem, not + // the Window. + // In case enabling (or even disabling) causes menu-related events (like + // pressing) that may execute callbacks potentially destroying the Window via + // the outer architecture. + WindowDestructionReceiver destruction_receiver(this); + main_menu_->SetEnabled(enabled); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + // Modifying the state of the items, notify the implementation so it makes the + // displaying of the main menu consistent. + CompleteMainMenuItemsUpdate(); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } +} + +void Window::CaptureMouse() { + ++mouse_capture_request_count_; + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + // Call even if capturing while the mouse is already assumed to be captured, + // in case something has released it in the OS. + ApplyNewMouseCapture(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::ReleaseMouse() { + assert_not_zero(mouse_capture_request_count_); + if (!mouse_capture_request_count_) { + return; + } + if (--mouse_capture_request_count_) { + return; + } + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewMouseRelease(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::SetCursorVisibility(CursorVisibility new_cursor_visibility) { + if (cursor_visibility_ == new_cursor_visibility) { + return; + } + CursorVisibility old_cursor_visibility = cursor_visibility_; + cursor_visibility_ = new_cursor_visibility; + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewCursorVisibility(old_cursor_visibility); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::Focus() { + if (!CanApplyState() || has_focus_) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + FocusImpl(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::SetPresenter(Presenter* presenter) { + if (presenter_ == presenter) { + return; + } + if (presenter_) { + presenter_->SetWindowSurfaceFromUIThread(nullptr, nullptr); + presenter_surface_.reset(); + } + presenter_ = presenter; + if (presenter_) { + presenter_surface_ = CreateSurface(presenter_->GetSupportedSurfaceTypes()); + presenter_->SetWindowSurfaceFromUIThread(this, presenter_surface_.get()); + } +} + +void Window::OnSurfaceChanged(bool new_surface_potentially_exists) { + if (!presenter_) { return; } - imgui_drawer_.reset(); + // Detach the presenter from the old surface before attaching to the new one. + if (presenter_surface_) { + presenter_->SetWindowSurfaceFromUIThread(this, nullptr); + presenter_surface_.reset(); + } - // Context must go last. - context_.reset(); -} - -void Window::Layout() { - UIEvent e(this); - OnLayout(&e); -} - -void Window::Invalidate() {} - -void Window::OnDpiChanged(UIEvent* e) { - // TODO(DrChat): Notify listeners. -} - -void Window::OnResize(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnResize(e); }); -} - -void Window::OnLayout(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnLayout(e); }); -} - -void Window::OnPaint(UIEvent* e) { - if (!context_) { + if (!new_surface_potentially_exists) { return; } - ++frame_count_; - ++fps_frame_count_; - static auto tick_frequency = Clock::QueryHostTickFrequency(); - auto now_ticks = Clock::QueryHostTickCount(); - // Average fps over 1 second. - if (now_ticks > fps_update_time_ticks_ + tick_frequency * 1) { - fps_ = static_cast( - fps_frame_count_ / - (static_cast(now_ticks - fps_update_time_ticks_) / - tick_frequency)); - fps_update_time_ticks_ = now_ticks; - fps_frame_count_ = 0; + presenter_surface_ = CreateSurface(presenter_->GetSupportedSurfaceTypes()); + if (presenter_surface_) { + presenter_->SetWindowSurfaceFromUIThread(this, presenter_surface_.get()); + } +} + +void Window::OnBeforeClose(WindowDestructionReceiver& destruction_receiver) { + // Because events are not sent from closed windows, and to make sure the + // window isn't closed while its surface is still attached to the presenter, + // this must be called before doing what constitutes closing in the platform + // implementation, not after. + + bool was_open = phase_ == Phase::kOpen; + bool was_open_or_opening = was_open || phase_ == Phase::kOpening; + assert_true(was_open_or_opening); + if (!was_open_or_opening) { + return; } - GraphicsContextLock context_lock(context_.get()); + if (was_open) { + phase_ = Phase::kOpenBeforeClosing; - // Prepare ImGui for use this frame. - auto& io = imgui_drawer_->GetIO(); - if (!last_paint_time_ticks_) { - io.DeltaTime = 0.0f; - last_paint_time_ticks_ = now_ticks; + // If the window was focused, notify the listeners that focus is being lost + // because the window is being closed (the implementation usually wouldn't + // be sending any events to the listeners after OnClosing even if the OS + // actually sends the focus loss event as part of the closing process). + OnFocusUpdate(false, destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + + { + UIEvent e(this); + SendEventToListeners([&e](auto listener) { listener->OnClosing(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + } + + // Disconnect from the surface without connecting to the new one (after the + // listeners so they don't try to reconnect afterwards). + OnSurfaceChanged(false); + } + + phase_ = Phase::kClosing; +} + +void Window::OnAfterClose() { + assert_true(phase_ == Phase::kClosing); + if (phase_ != Phase::kClosing) { + return; + } + phase_ = (innermost_listener_iteration_context_ || + innermost_input_listener_iteration_context_) + ? Phase::kClosedLeavingListeners + : Phase::kClosedOpenable; +} + +void Window::OnDpiChanged(UISetupEvent& e, + WindowDestructionReceiver& destruction_receiver) { + SendEventToListeners([&e](auto listener) { listener->OnDpiChanged(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } +} + +void Window::OnMonitorUpdate(MonitorUpdateEvent& e) { + if (presenter_surface_) { + presenter_->OnSurfaceMonitorUpdateFromUIThread( + e.old_monitor_potentially_disconnected()); + } +} + +bool Window::OnActualSizeUpdate( + uint32_t new_physical_width, uint32_t new_physical_height, + WindowDestructionReceiver& destruction_receiver) { + if (actual_physical_width_ == new_physical_width && + actual_physical_height_ == new_physical_height) { + return false; + } + actual_physical_width_ = new_physical_width; + actual_physical_height_ = new_physical_height; + // The listeners may reference the presenter, update the presenter first. + if (presenter_surface_) { + presenter_->OnSurfaceResizeFromUIThread(); + } + UISetupEvent e(this); + SendEventToListeners([&e](auto listener) { listener->OnResize(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return true; + } + return true; +} + +void Window::OnFocusUpdate(bool new_has_focus, + WindowDestructionReceiver& destruction_receiver) { + if (has_focus_ == new_has_focus) { + return; + } + has_focus_ = new_has_focus; + UISetupEvent e(this); + if (has_focus_) { + SendEventToListeners([&e](auto listener) { listener->OnGotFocus(e); }, + destruction_receiver); } else { - io.DeltaTime = (now_ticks - last_paint_time_ticks_) / - static_cast(tick_frequency); - last_paint_time_ticks_ = now_ticks; + SendEventToListeners([&e](auto listener) { listener->OnLostFocus(e); }, + destruction_receiver); } - io.DisplaySize = ImVec2(static_cast(scaled_width()), - static_cast(scaled_height())); - - bool can_swap = context_->BeginSwap(); - if (context_->WasLost()) { - on_context_lost(e); + if (destruction_receiver.IsWindowDestroyed()) { return; } - if (!can_swap) { - // Surface not available. +} + +void Window::OnPaint(bool force_paint) { + if (is_painting_) { return; } + is_painting_ = true; + if (presenter_surface_) { + presenter_->PaintFromUIThread(force_paint); + } + is_painting_ = false; +} - ImGui::NewFrame(); - - ForEachListener([e](auto listener) { listener->OnPainting(e); }); - on_painting(e); - ForEachListener([e](auto listener) { listener->OnPaint(e); }); - on_paint(e); - - // Flush ImGui buffers before we swap. - ImGui::Render(); - imgui_drawer_->RenderDrawLists(); - - ForEachListener([e](auto listener) { listener->OnPainted(e); }); - on_painted(e); - - context_->EndSwap(); - - // If animations are running, reinvalidate immediately. - if (kContinuousRepaint) { - Invalidate(); +void Window::OnFileDrop(FileDropEvent& e, + WindowDestructionReceiver& destruction_receiver) { + SendEventToListeners([&e](auto listener) { listener->OnFileDrop(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; } } -void Window::OnFileDrop(FileDropEvent* e) { - on_file_drop(e); - ForEachListener([e](auto listener) { listener->OnFileDrop(e); }); +void Window::OnKeyDown(KeyEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnKeyDown(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnVisible(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnVisible(e); }); +void Window::OnKeyUp(KeyEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnKeyUp(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnHidden(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnHidden(e); }); +void Window::OnKeyChar(KeyEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnKeyChar(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnGotFocus(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnGotFocus(e); }); +void Window::OnMouseDown(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnMouseDown(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnLostFocus(UIEvent* e) { - modifier_shift_pressed_ = false; - modifier_cntrl_pressed_ = false; - modifier_alt_pressed_ = false; - modifier_super_pressed_ = false; - ForEachListener([e](auto listener) { listener->OnLostFocus(e); }); +void Window::OnMouseMove(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnMouseMove(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnKeyPress(KeyEvent* e, bool is_down, bool is_char) { - if (!is_char) { - switch (e->virtual_key()) { - case VirtualKey::kShift: - modifier_shift_pressed_ = is_down; - break; - case VirtualKey::kControl: - modifier_cntrl_pressed_ = is_down; - break; - case VirtualKey::kMenu: - modifier_alt_pressed_ = is_down; - break; - case VirtualKey::kLWin: - modifier_super_pressed_ = is_down; - break; - default: - break; +void Window::OnMouseUp(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnMouseUp(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } +} + +void Window::OnMouseWheel(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnMouseWheel(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } +} + +void Window::SendEventToListeners( + std::function fn, + WindowDestructionReceiver& destruction_receiver) { + if (!CanSendEventsToListeners()) { + return; + } + ListenerIterationContext iteration_context( + innermost_listener_iteration_context_); + innermost_listener_iteration_context_ = &iteration_context; + while (iteration_context.next_index < listeners_.size()) { + // iteration_context.next_index may be changed during the execution of the + // listener if the list of the listeners is modified by it - don't assume + // that after the call iteration_context.next_index will be the same as + // iteration_context.next_index + 1 before it. + fn(listeners_[iteration_context.next_index++]); + if (destruction_receiver.IsWindowDestroyed()) { + // The window was destroyed by the listener, can't access anything in + // *this anymore, including innermost_listener_iteration_context_ which + // has to be left in an indeterminate state. + return; + } + if (!CanSendEventsToListeners()) { + // The listener has put the window in a state in which the window can't + // send events anymore. + break; } } + assert_true(innermost_listener_iteration_context_ == &iteration_context); + innermost_listener_iteration_context_ = + innermost_listener_iteration_context_->outer_context; + if (phase_ == Phase::kClosedLeavingListeners && + !innermost_listener_iteration_context_ && + !innermost_input_listener_iteration_context_) { + phase_ = Phase::kClosedOpenable; + } } -void Window::OnKeyDown(KeyEvent* e) { - on_key_down(e); - if (e->is_handled()) { +void Window::PropagateEventThroughInputListeners( + std::function fn, + WindowDestructionReceiver& destruction_receiver) { + if (!CanSendEventsToListeners()) { return; } - TryForEachListener([e](auto listener) { - listener->OnKeyDown(e); - return e->is_handled(); - }); - OnKeyPress(e, true, false); -} - -void Window::OnKeyUp(KeyEvent* e) { - on_key_up(e); - if (e->is_handled()) { - return; + InputListenerIterationContext iteration_context( + innermost_input_listener_iteration_context_, input_listeners_.crbegin()); + innermost_input_listener_iteration_context_ = &iteration_context; + while (iteration_context.next_iterator != input_listeners_.crend()) { + // The current iterator may be invalidated, and + // iteration_context.next_iterator may be changed, during the execution of + // the listener if the list of the listeners is modified by it - don't + // assume that after the call iteration_context.next_iterator will be the + // same as std::next(iteration_context.next_iterator) before it. + iteration_context.current_z_order = iteration_context.next_iterator->first; + bool event_handled = fn((iteration_context.next_iterator++)->second); + if (destruction_receiver.IsWindowDestroyed()) { + // The window was destroyed by the listener, can't access anything in + // *this anymore, including innermost_listener_iteration_context_ which + // has to be left in an indeterminate state. + return; + } + if (event_handled) { + break; + } + if (!CanSendEventsToListeners()) { + // The listener has put the window in a state in which the window can't + // send events anymore. + break; + } } - TryForEachListener([e](auto listener) { - listener->OnKeyUp(e); - return e->is_handled(); - }); - OnKeyPress(e, false, false); -} - -void Window::OnKeyChar(KeyEvent* e) { - OnKeyPress(e, true, true); - on_key_char(e); - ForEachListener([e](auto listener) { listener->OnKeyChar(e); }); - OnKeyPress(e, false, true); -} - -void Window::OnMouseDown(MouseEvent* e) { - on_mouse_down(e); - if (e->is_handled()) { - return; + assert_true(innermost_input_listener_iteration_context_ == + &iteration_context); + innermost_input_listener_iteration_context_ = + innermost_input_listener_iteration_context_->outer_context; + if (phase_ == Phase::kClosedLeavingListeners && + !innermost_listener_iteration_context_ && + !innermost_input_listener_iteration_context_) { + phase_ = Phase::kClosedOpenable; } - TryForEachListener([e](auto listener) { - listener->OnMouseDown(e); - return e->is_handled(); - }); -} - -void Window::OnMouseMove(MouseEvent* e) { - on_mouse_move(e); - if (e->is_handled()) { - return; - } - TryForEachListener([e](auto listener) { - listener->OnMouseMove(e); - return e->is_handled(); - }); -} - -void Window::OnMouseUp(MouseEvent* e) { - on_mouse_up(e); - if (e->is_handled()) { - return; - } - TryForEachListener([e](auto listener) { - listener->OnMouseUp(e); - return e->is_handled(); - }); -} - -void Window::OnMouseWheel(MouseEvent* e) { - on_mouse_wheel(e); - if (e->is_handled()) { - return; - } - TryForEachListener([e](auto listener) { - listener->OnMouseWheel(e); - return e->is_handled(); - }); } } // namespace ui diff --git a/src/xenia/ui/window.h b/src/xenia/ui/window.h index 2627c7ca0..564eaeaea 100644 --- a/src/xenia/ui/window.h +++ b/src/xenia/ui/window.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,209 +10,711 @@ #ifndef XENIA_UI_WINDOW_H_ #define XENIA_UI_WINDOW_H_ +#include +#include +#include #include #include +#include -#include "xenia/base/delegate.h" #include "xenia/base/platform.h" -#include "xenia/ui/graphics_context.h" #include "xenia/ui/menu_item.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/surface.h" #include "xenia/ui/ui_event.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app_context.h" namespace xe { namespace ui { -typedef void* NativePlatformHandle; -typedef void* NativeWindowHandle; - -class ImGuiDrawer; - class Window { public: - static std::unique_ptr Create(WindowedAppContext& app_context_, - const std::string& title); + // Transitions between these phases is sequential and looped (and >= and <= + // can be used for openness checks, for closedness checks ! of >= and <= is + // needed due to looping), with the exception of kDeleting that may be entered + // from any other state (with an assertion for that not being done during + // kOpening though as that's extremely dangerous and would require a lot of + // handling in OpenImpl on all platforms) as the Window object may be deleted + // externally at any moment, and the Window will have no control anymore when + // that happens. Another exception is that the window may be closed in the + // platform during kOpening - in this case, it will skip kOpenBeforeClosing + // and go directly to kClosing and beyond. + enum class Phase { + // The window hasn't been opened yet, or has been fully closed and can be + // reopened. + // No native window - external state updates change only the desired state, + // don't go to the implementation immediately. + // No actual state. + // Listeners are not called. + kClosedOpenable, + // OpenImpl is being invoked, the implementation is performing initial + // setup. + // External state changes are functionally near-impossible as OpenImpl + // mostly isn't able to communicate with external Xenia code that may have + // any effect on the Window, to avoid interference during the native window + // setup which may be pretty complex - and also, this is the phase in which + // the native window is being created, so there's no guarantee that the + // native window exists throughout this phase. + // However, it's still not strictly enforceable that OpenImpl will not cause + // any interaction with the Window - it may happen, for instance, if + // OpenImpl causes the OS to execute the pending functions in the + // WindowedAppContext that might have been, for example, left over from when + // the window was still open last time. Therefore, for the reason of state + // consistency within OpenImpl, all external state changes are simply + // dropped in this phase. + // However, the desired state may be updated by the implementation during + // OpenImpl still, but via the Update functions (if the implementation or + // the OS, for instance, clamps the size of the window during creation, or + // refuses to enter fullscreen). + // Actual state is first populated during this phase, and it's readable + // (with its level of completeness at the specific point in time) for the + // internal purposes of the implementation. + // Listeners are not called so the implementation can perform all the setup + // without outer interference (the common code calls some to let the + // listeners be aware of the initial state when the window enters kOpen + // anyway). + // Note: Closing may occur in the platform during kOpening - skip + // kOpenBeforeClosing in this case while closing. + kOpening, + // Fully interactive. + // The native window exists, external state changes are applied immediately + // (or at least immediately requested to be applied shortly after, but the + // implementation must make sure that, for instance, if SetFullscreen is + // successfully called, but the window will actually enter fullscreen only + // at the next platform event loop tick, IsFullscreen will start returning + // true immediately). + // The desired state can be updated as feedback from the implementation. + // Actual state can be retrieved. + // Listeners are called. + // The only state in which a non-null Surface can be created (it's destroyed + // after entering kClosing). + kOpen, + // OnBeforeClose is being invoked. + // The native window still exists, this is mostly like kOpen, but with no + // way of creating a Surface (it's becoming destroyed in this state so the + // native window can be destroyed safely in the next phase) or recursively + // requesting closing - for consistency during closing within the platform, + // state changes also behave like in kOpen. + // Listeners are still called as normal, primarily because this is where the + // OnClosing listener function is invoked, but reopening the window from a + // listener is not possible for state consistency during closing. + kOpenBeforeClosing, + // OnBeforeClose has completed, but OnAfterClose hasn't been called yet for + // the implementation to confirm that it has finished destroying the native + // window being closed. This state exists to prevent the situation in which + // the Window is somehow reopened in the middle of the implementation's + // internal work in closing. + // The implementation must detach from the native window and destroy it in + // this phase. + // The native window is being destroyed - external state updates change only + // the desired state, don't go to the implementation immediately. + // Actual state is still queryable for internal purposes of the + // implementation. + // Listeners are not called. + kClosing, + // OnBeforeClose has completed, but the close has occurred from a listener, + // and the call stack of listeners still hasn't been exited. + // This state exists to prevent the situation in which the Window is being + // closed and then reopened in the middle of the implementation's internal + // work in event handlers. For example, let's assume putting a window (HWND) + // in the fullscreen state requires removing window decorations + // (SetWindowLong) and resizing the window (SetWindowPos), both being able + // to invoke the resize handler (WM_SIZE) and thus the resize listener. In + // this case, consider the following situation: + // - SetWindowLong called for HWND. + // - WM_SIZE arrives. + // - Listener's OnResize called. + // - Listener's OnResize does RequestClose, destroying the current HWND. + // - Listener's OnResize does Open, creating a new HWND. + // - SetWindowPos called for HWND, which is different now. + // Here, SetWindowLong will be called for one native window, but then it + // will be replaced, and SetWindowPos will be called for a different one. + // No native window - external state updates change only the desired state, + // don't go to the implementation immediately. + // No actual state. + // Listeners are not called. + kClosedLeavingListeners, + // The destructor has been called - should transition into this before doing + // anything not only in the common, but in the implementation's destructor + // as well. The transition must be done regardless of the previous phase as + // there's no way the Window can stop its destruction from now on. This is + // mostly similar to kClosedLeavingListeners, except there's no way to leave + // this phase. + kDeleting, + }; + + enum class CursorVisibility { + kVisible, + // Temporarily revealed, hidden if not interacting with the mouse. + kAutoHidden, + kHidden, + }; + + static std::unique_ptr Create(WindowedAppContext& app_context, + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height); virtual ~Window(); WindowedAppContext& app_context() const { return app_context_; } - virtual NativePlatformHandle native_platform_handle() const = 0; - virtual NativeWindowHandle native_handle() const = 0; - - MenuItem* main_menu() const { return main_menu_.get(); } - void set_main_menu(std::unique_ptr main_menu) { - main_menu_ = std::move(main_menu); - OnMainMenuChange(); + Phase phase() const { return phase_; } + bool HasActualState() const { + // kOpening - for internal use by the implementation. + // kOpen, kOpenBeforeClosing - for both external and internal use. + // kClosing - for internal use by the implementation. + return phase_ >= Phase::kOpening && phase_ <= Phase::kClosing; } - virtual void EnableMainMenu() = 0; - virtual void DisableMainMenu() = 0; + void AddListener(WindowListener* listener); + void RemoveListener(WindowListener* listener); + void AddInputListener(WindowInputListener* listener, size_t z_order); + void RemoveInputListener(WindowInputListener* listener); - const std::string& title() const { return title_; } - virtual bool set_title(const std::string_view title) { - if (title == title_) { - return false; + // `false` is returned only in case of an error while trying to perform the + // platform window opening. If the window is already open, or just can't be + // reopened in the current phase (as in this case it's assumed that the outer + // will handle this situation properly and won't, for instance, leave a + // process without windows - it will quit the application in OnBeforeClose of + // the window closing of which was initiated before or even during opening, + // for instance), `true` is returned. The functions of WindowListeners will be + // called only for a newly opened platform window - and the listeners may + // close or even destroy the window, in which case this function will still + // return `true` to differentiate from an actual error - if it's really + // necessary that the platform window is open after the call, check phase() + // after calling. + bool Open(); + // The call may or may not close the window immediately, depending on the + // platform (phase() may still return an open phase, and events may still be + // sent after the call). Use phase() to check if closing has actually + // happened immediately. + void RequestClose() { + // Don't allow external close requests during opening for state consistency + // inside OpenImpl (if an internal close happens during OpenImpl, the + // implementation will be aware of that at least), and don't allow closing + // twice. + if (phase_ != Phase::kOpen) { + return; } - title_ = title; - return true; + RequestCloseImpl(); + // Must not doing anything else with *this as callbacks might have been + // triggered during closing (if it has actually even happened), and the + // Window might have been deleted. } - virtual bool SetIcon(const void* buffer, size_t size) = 0; + // The `public` state setters are for calling from outside. + // The implementation must use the public getters to obtain the desired state + // while applying, but for updating the actual state, or for overriding the + // desired state, the `protected` On*Update functions must be used (overall + // the On* functions are for the implementation's feedback). + + virtual uint32_t GetMediumDpi() const { return 96; } + uint32_t GetDpi() const { + uint32_t dpi = GetLatestDpiImpl(); + return dpi ? dpi : GetMediumDpi(); + } + + // Round trips are not guaranteed to return the same results. + static constexpr uint32_t ConvertSizeDpi(uint32_t size, uint32_t new_dpi, + uint32_t old_dpi) { + // Always rounding up to prevent zero sizes (unless the input is zero) as + // well as gaps at the edge. + return uint32_t((uint64_t(size) * new_dpi + (old_dpi - 1)) / old_dpi); + } + uint32_t SizeToLogical(uint32_t size) const { + return ConvertSizeDpi(size, GetMediumDpi(), GetDpi()); + } + uint32_t SizeToPhysical(uint32_t size) const { + return ConvertSizeDpi(size, GetDpi(), GetMediumDpi()); + } + static constexpr int32_t ConvertPositionDpi(int32_t position, + uint32_t new_dpi, + uint32_t old_dpi) { + // Rounding to the nearest mostly similar to Windows MulDiv. + // Plus old_dpi / 2 for positive values, minus old_dpi / 2 for negative + // values for consistent rounding for both positive and negative values (as + // the `/` operator rounds towards zero). + // Example: + // (-3 - 1) / 3 == -1 + // (-2 - 1) / 3 == -1 + // (-1 - 1) / 3 == 0 + // --- + // (0 + 1) / 3 == 0 + // (1 + 1) / 3 == 0 + // (2 + 1) / 3 == 1 + return int32_t((int64_t(position) * new_dpi + + int32_t(old_dpi >> 1) * (position < 0 ? -1 : 1)) / + old_dpi); + } + int32_t PositionToLogical(int32_t position) const { + return ConvertPositionDpi(position, GetMediumDpi(), GetDpi()); + } + int32_t PositionToPhysical(int32_t position) const { + return ConvertPositionDpi(position, GetDpi(), GetMediumDpi()); + } + + // The desired logical size of the window when it's not maximized, regardless + // of the current state of the window (maximized, fullscreen, etc.) + // The implementation may update it, for instance, to clamp it, or when the + // user resizes a non-maximized window. + uint32_t GetDesiredLogicalWidth() const { return desired_logical_width_; } + uint32_t GetDesiredLogicalHeight() const { return desired_logical_height_; } + + // 0 width or height may be returned even in case of an open window with a + // valid non-zero-area surface depending on the platform. + uint32_t GetActualPhysicalWidth() const { + return HasActualState() ? actual_physical_width_ : 0; + } + uint32_t GetActualPhysicalHeight() const { + return HasActualState() ? actual_physical_height_ : 0; + } + uint32_t GetActualLogicalWidth() const { + return SizeToLogical(GetActualPhysicalWidth()); + } + uint32_t GetActualLogicalHeight() const { + return SizeToLogical(GetActualPhysicalHeight()); + } + + // Desired state stored by the common Window, modifiable both externally and + // by the implementation (including from SetFullscreen itself). + virtual bool IsFullscreen() const { return fullscreen_; } + void SetFullscreen(bool new_fullscreen); + + // Desired state stored by the common Window, externally modifiable, read-only + // in the implementation. + const std::string& GetTitle() const { return title_; } + void SetTitle(const std::string_view new_title); + + // Desired state stored in a platform-dependent way in the implementation, + // externally modifiable, read-only by the implementation unless from the + // LoadAndApplyIcon implementation. The icon is in Windows .ico format. + // Provide null buffer and / or zero size to reset the icon. + void SetIcon(const void* buffer, size_t size); void ResetIcon() { SetIcon(nullptr, 0); } - virtual bool CaptureMouse() = 0; - virtual bool ReleaseMouse() = 0; + // Desired state stored by the common Window, externally modifiable, read-only + // in the implementation. + void SetMainMenu(std::unique_ptr new_main_menu); + void CompleteMainMenuItemsUpdate(); + void SetMainMenuEnabled(bool enabled); - virtual bool is_fullscreen() const { return false; } - virtual void ToggleFullscreen(bool fullscreen) {} - - virtual bool is_bordered() const { return false; } - virtual void set_bordered(bool enabled) {} - - virtual int get_medium_dpi() const { return 96; } - virtual int get_dpi() const { return get_medium_dpi(); } - virtual float get_dpi_scale() const { - return float(get_dpi()) / float(get_medium_dpi()); + // Desired state stored by the common Window, externally modifiable, read-only + // in the implementation. + bool IsMouseCaptureRequested() const { + return mouse_capture_request_count_ != 0; } + void CaptureMouse(); + void ReleaseMouse(); - bool has_focus() const { return has_focus_; } - virtual void set_focus(bool value) { has_focus_ = value; } + // Desired state stored by the common Window, externally modifiable, read-only + // in the implementation. + CursorVisibility GetCursorVisibility() const { return cursor_visibility_; } + // Setting this to kAutoHidden from any _other_ visibility should hide the + // cursor immediately - for instance, if the external code wants to auto-hide + // the cursor in fullscreen, to allow going into the fullscreen mode to hide + // the cursor instantly. + void SetCursorVisibility(CursorVisibility new_cursor_visibility); - bool is_cursor_visible() const { return is_cursor_visible_; } - virtual void set_cursor_visible(bool value) { is_cursor_visible_ = value; } + bool HasFocus() const { return HasActualState() ? has_focus_ : false; } + // May be applied in a delayed way or dropped at all, HasFocus will not + // necessarily be true immediately. + void Focus(); - // TODO(Triang3l): Don't scale for guest output - use physical pixels. Use - // logical pixels only for the immediate drawer. - int32_t width() const { return width_; } - int32_t height() const { return height_; } - int32_t scaled_width() const { return int32_t(width_ * get_dpi_scale()); } - int32_t scaled_height() const { return int32_t(height_ * get_dpi_scale()); } + // TODO(Triang3l): A resize function, primarily for snapping externally to + // 1280x720, 1920x1080, and other 1:1 resolutions. It will need to resize the + // window (to a desired logical size - the actual physical size is entirely + // the feedback of the implementation) in the normal state, and possibly also + // un-maximize (and possibly un-fullscreen) it (but this choice will possibly + // need to be exposed to the caller). Because it's currently not needed, it's + // not implemented to avoid platform-specific complexities regarding + // maximization, DPI, etc. - virtual void Resize(int32_t width, int32_t height) { - width_ = width; - height_ = height; + void SetPresenter(Presenter* presenter); + + // Request repainting of the surface. Can be called from non-UI threads as + // long as they know the Surface exists and isn't in the middle of being + // changed to another (the synchronization of this fact between the UI thread + // and the caller thread must be done externally through OnSurfaceChanged). + void RequestPaint() { + if (presenter_surface_) { + RequestPaintImpl(); + } } - virtual void Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) { - width_ = right - left; - height_ = bottom - top; - } - - GraphicsContext* context() const { return context_.get(); } - ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); } - bool is_imgui_input_enabled() const { return is_imgui_input_enabled_; } - void set_imgui_input_enabled(bool value); - - void AttachListener(WindowListener* listener); - void DetachListener(WindowListener* listener); - - virtual bool Initialize() { return true; } - void set_context(std::unique_ptr context) { - context_ = std::move(context); - if (context_) { - MakeReady(); + void RequestPresenterUIPaintFromUIThread() { + if (presenter_) { + presenter_->RequestUIPaintFromUIThread(); } } - void Layout(); - virtual void Invalidate(); - - virtual void Close() = 0; - - public: - Delegate on_closing; - Delegate on_closed; - - Delegate on_painting; - Delegate on_paint; - Delegate on_painted; - Delegate on_context_lost; - - Delegate on_file_drop; - - Delegate on_key_down; - Delegate on_key_up; - Delegate on_key_char; - - Delegate on_mouse_down; - Delegate on_mouse_move; - Delegate on_mouse_up; - Delegate on_mouse_wheel; - protected: - Window(WindowedAppContext& app_context, const std::string& title); + // The receiver, which must never be instantiated in the Window object itself + // (rather, usually it should be created as a local variable, because only + // LIFO-ordered creation and deletion of these is supported), that allows + // deletion of the Window from within an event handler (which may invoke a + // WindowListener, and window listeners are allowed to destroy windows; also + // they may execute, for instance, the functions requested to be executed in + // the UI thread in the WindowedAppContext, which are also allowed to destroy + // windows - because if the former wasn't allowed, the latter would be + // required to destroy windows as a result of UI interaction) to be caught by + // functions inside the Window in order to stop interacting with `*this` and + // returning after this happens. + // Note that the receivers are signaled in the *end* of the destruction of the + // common Window, when truly nothing can be done with it anymore, so it's safe + // to assume that right after the creation of the WindowDestructionReceiver, + // it will still be in an unsignaled state even if it's used somewhere in the + // destructor. The reason is that the users of the WindowDestructionReceiver + // are expected to stop accessing the Window *immediately* once + // IsWindowDestroyed becomes `true`, and to leave it in a potentially + // indeterminate state - but the code executed subsequently in the destructor + // may still use that state meaningfully. + class WindowDestructionReceiver { + public: + explicit WindowDestructionReceiver(Window* window) : window_(window) { + if (window_) { + outer_receiver_ = window_->innermost_destruction_receiver_; + window_->innermost_destruction_receiver_ = this; + } + } - void ForEachListener(std::function fn); - void TryForEachListener(std::function fn); + ~WindowDestructionReceiver() { + // If the window is not null, removal from the stack must happen + // regardless of `phase_ == Phase::kDeleting`, because the window + // destructor iterates the receivers after EnterDestructor(), and if the + // receiver is not removed in this case, the destructor will do + // use-after-free. + if (window_) { + // Only LIFO order is supported (normally through RAII). + assert_true(window_->innermost_destruction_receiver_ == this); + window_->innermost_destruction_receiver_ = outer_receiver_; + } + } - virtual bool MakeReady(); + bool IsWindowDestroyed() const { return window_ == nullptr; } - virtual bool OnCreate(); - virtual void OnMainMenuChange(); - virtual void OnClose(); - virtual void OnDestroy(); + // Helper functions for common usages of the receiver. Unlike + // IsWindowDestroyed, these, however, may return false immediately on + // creation. + // Primarily for the implementation (most importantly its native event + // handler), to stop interacting with the native window given that it was + // possible before the function call it's guarded with. + bool IsWindowDestroyedOrClosed() const { + return IsWindowDestroyed() || window_->IsClosed(); + } + // For guarding Apply* calls if one state setter needs to make multiple of + // them (or just detecting if it's okay to call Apply*). + bool IsWindowDestroyedOrStateInapplicable() const { + return IsWindowDestroyed() || !window_->CanApplyState(); + } + bool IsWindowDestroyedOrListenersUncallable() const { + return IsWindowDestroyed() || !window_->CanSendEventsToListeners(); + } - virtual void OnDpiChanged(UIEvent* e); - virtual void OnResize(UIEvent* e); - virtual void OnLayout(UIEvent* e); - virtual void OnPaint(UIEvent* e); - virtual void OnFileDrop(FileDropEvent* e); + private: + // The Window must set window_ to nullptr in its destructor. + friend Window; + Window* window_; + WindowDestructionReceiver* outer_receiver_ = nullptr; + }; - virtual void OnVisible(UIEvent* e); - virtual void OnHidden(UIEvent* e); + // Like in the Windows Media Player. + // A more modern Windows example, Movies & TV in Windows 11 21H2, has 5000, + // but it's too long especially for highly dynamic games. + // Implementations may use different values according to the platform's UX + // conventions. + static constexpr uint32_t kDefaultCursorAutoHideMilliseconds = 3333; - virtual void OnGotFocus(UIEvent* e); - virtual void OnLostFocus(UIEvent* e); + Window(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height); - virtual void OnKeyDown(KeyEvent* e); - virtual void OnKeyUp(KeyEvent* e); - virtual void OnKeyChar(KeyEvent* e); + // If implementation-specific destruction happens, should be called in the + // beginning of the implementation's destructor so the implementation can + // destroy the platform window without doing something unsafe in destruction. + void EnterDestructor() { + phase_ = Phase::kDeleting; + // Disconnect from the surface before destroying the window behind it. + OnSurfaceChanged(false); + } - virtual void OnMouseDown(MouseEvent* e); - virtual void OnMouseMove(MouseEvent* e); - virtual void OnMouseUp(MouseEvent* e); - virtual void OnMouseWheel(MouseEvent* e); + // For an open window, the implementation should return the current DPI for + // the window. For a non-open one, it should be the closest approximation, + // such as the last DPI from an existing window, the system DPI, or just the + // medium DPI (0 returned from it will also be treated as medium DPI). + virtual uint32_t GetLatestDpiImpl() const { return GetMediumDpi(); } - void OnKeyPress(KeyEvent* e, bool is_down, bool is_char); + // Deletion of the window may (and must) not happen in OpenImpl, the listeners + // are deferred, so there's no need to use WindowDestructionReceiver in it. + // In case of failure, the implementation must not leave itself in an + // indeterminate state, so another attempt to open the window can be made. + // The implementation must apply the following desired state if it needs it, + // directly (not via Set* methods as they will be dropped during OpenImpl + // since the window is not fully open yet): + // - Title (GetTitle()). + // - Icon (from the last LoadAndApplyIcon call). + // - Main menu (GetMainMenu()) and its enablement. + // - Desired logical size (GetDesiredLogicalWidth() / Height(), taking into + // account that the main menu, during the initial opening, should not be + // included in this size - it specifies the client area that painting will + // be done to), within the capabilities of the platform (may be clamped by + // the OS, for instance - in this case, OnDesiredLogicalSizeUpdate may be + // called from within OpenImpl to store the clamped size for later). + // - Fullscreen (GetFullscreen()) - however, if possible, the calculations + // that would normally be done for a non-fullscreen window in OpenImpl + // should also be done if entering fullscreen, including the menu-related + // ones - first, the usual windowed geometry calculations should be done, + // and then fullscreen should be entered; but preferably still entering + // fullscreen before actually showing a visible window to the user for a + // seamless transition. + // - Mouse capture (IsMouseCaptureRequested()). + // - Cursor visibility (GetCursorVisibility()). + // Also, as a result of the OpenImpl call, these function should be called + // (immediately from within OpenImpl directly or indirectly through the native + // event handling, or shortly after during the UI main loop) to provide the + // initial actual state to the common Window code so it returns the correct + // values: + // - OnActualSizeUpdate, at least if the window isn't opened as not yet + // visible on screen (otherwise the size will be assumed to be 0x0 until the + // next size update caused by something likely requiring user interaction). + // - OnFocusUpdate, at least if the focus has been obtained (otherwise the + // window will be assumed to be not in focus until it goes into the focus + // again). + // Also, if some of the desired state that may be updated by the + // implementation could not be applied (such as the fullscreen mode), and + // certain values of the implementation state are either normally + // differentiated within the implementation or are just meaningful considering + // the platform's defaults (for instance, the platform inherently supports + // only fullscreen, possibly doesn't have a concept of windows at all), it's + // recommended to call the appropriate On*Update functions to update the + // desired state to the actual one. + virtual bool OpenImpl() = 0; + virtual void RequestCloseImpl() = 0; + + // Apply* are called only if CanApplyState() is true (unless the function + // should do more than just applying, such as also updating the desired state + // in a platform-dependent way - see each individual function). + // ApplyNew* means that the value has actually been changed to something + // different than it was previously. + virtual void ApplyNewFullscreen() {} + virtual void ApplyNewTitle() {} + // can_apply_state_in_current_phase whether the window is in a life cycle + // phase that would normally accept Apply calls (the native window surely + // exists), since this function may be called in closed states too to update + // the desired icon (since it's stored in the implementation) - the + // implementation may, however, ignore it and use a more granular check of the + // existence of the native window and the safety of updating the icon for + // better internal state consistency. The icon is in Windows .ico format. If + // the buffer is null or the size is 0, the icon should be reset to the + // default one. Returns whether the icon has been updated successfully. + virtual void LoadAndApplyIcon(const void* buffer, size_t size, + bool can_apply_state_in_current_phase) {} + MenuItem* GetMainMenu() const { return main_menu_.get(); } + // May be called to add, replace or remove the main menu. + virtual void ApplyNewMainMenu(MenuItem* old_main_menu) {} + // If there's main menu, and state can be applied, will be called to make the + // implementation's state consistent with the new state of the MenuItems of + // the main menu after changes have been made to them. + virtual void CompleteMainMenuItemsUpdateImpl() {} + // Will be called even if capturing while the mouse is already assumed to be + // captured, in case something has released it in the OS. + virtual void ApplyNewMouseCapture() {} + virtual void ApplyNewMouseRelease() {} + virtual void ApplyNewCursorVisibility( + CursorVisibility old_cursor_visibility) {} + // If state can be applied, this is called to request bringing the window into + // focus (and once that's done by the OS, update the actual focus state). Does + // nothing otherwise (focus can't be requested before the window is open, a + // closed window is always assumed to be not in focus). + virtual void FocusImpl() {} + + Presenter* presenter() const { return presenter_; } + bool HasSurface() const { return presenter_surface_ != nullptr; } + // If new_surface_potentially_exists is false, creation of the new surface for + // the window won't be updated, and it may be called from the destructor (via + // EnterDestructor to destroy the surface before destroying what it depends + // on) as no virtual functions (including CreateSurface) will be called. + // This function is nonvirtual itself for this reason as well. + void OnSurfaceChanged(bool new_surface_potentially_exists); + // Called only for an open window. + virtual std::unique_ptr CreateSurfaceImpl( + Surface::TypeFlags allowed_types) = 0; + // Called only if the Surface exists. + virtual void RequestPaintImpl() = 0; + + // Will also disconnect the surface if needed. + void OnBeforeClose(WindowDestructionReceiver& destruction_receiver); + void OnAfterClose(); + + // These functions may usually also be called as part of the opening process + // from within OpenImpl (directly or through the platform event handler + // invoked during it) to actualize the state for the newly createad window, + // especially if it's different than the desired one. + void OnDpiChanged(UISetupEvent& e, + WindowDestructionReceiver& destruction_receiver); + void OnMonitorUpdate(MonitorUpdateEvent& e); + // For calling when the platform changes something in the non-maximized, + // non-fullscreen size of the window. + void OnDesiredLogicalSizeUpdate(uint32_t new_desired_logical_width, + uint32_t new_desired_logical_height) { + desired_logical_width_ = new_desired_logical_width; + desired_logical_height_ = new_desired_logical_height; + } + // If the size of the client area is the same as the currently assumed one + // (the desired / last size for a newly opened / reopened window, the last + // actual size for an already open window), does nothing and returns false. + // Otherwise, updates the size, notifies what depends on the size about the + // change, and returns true. Not storing the new size in the UISetupEvent + // because a resize listener may request another resize, in which case it will + // be outdated - listeners must query the new physical size from the window + // explicitly. + bool OnActualSizeUpdate(uint32_t new_physical_width, + uint32_t new_physical_height, + WindowDestructionReceiver& destruction_receiver); + void OnDesiredFullscreenUpdate(bool new_fullscreen) { + fullscreen_ = new_fullscreen; + } + void OnFocusUpdate(bool new_has_focus, + WindowDestructionReceiver& destruction_receiver); + + // Pass true as force_paint in case the platform can't retain the image from + // the previous paint so it won't be skipped if there are no content updates. + void OnPaint(bool force_paint = false); + + void OnFileDrop(FileDropEvent& e, + WindowDestructionReceiver& destruction_receiver); + + void OnKeyDown(KeyEvent& e, WindowDestructionReceiver& destruction_receiver); + void OnKeyUp(KeyEvent& e, WindowDestructionReceiver& destruction_receiver); + void OnKeyChar(KeyEvent& e, WindowDestructionReceiver& destruction_receiver); + + void OnMouseDown(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver); + void OnMouseMove(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver); + void OnMouseUp(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver); + void OnMouseWheel(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver); + + private: + struct ListenerIterationContext { + explicit ListenerIterationContext(ListenerIterationContext* outer_context, + size_t first_index = 0) + : outer_context(outer_context), next_index(first_index) {} + // To support nested listener calls, in case a listener does some + // interaction with the window that results in more events being triggered + // (such as calling Windows API functions that return a result from a + // message handled by a window, rather that simply enqueueing the message). + ListenerIterationContext* outer_context; + // Using indices, not iterators, because after the erasure, the adjustment + // must be done for the vector element indices that would be in the iterator + // range that would be invalidated. + size_t next_index; + }; + + struct InputListenerIterationContext { + explicit InputListenerIterationContext( + InputListenerIterationContext* outer_context, + std::multimap::const_reverse_iterator + first_iterator, + size_t first_z_order = SIZE_MAX) + : outer_context(outer_context), + next_iterator(first_iterator), + current_z_order(first_z_order) {} + // To support nested listener calls. + InputListenerIterationContext* outer_context; + // Reverse iterator because input handlers with a higher Z order index may + // correspond to what's displayed on top of what has a lower Z order index, + // so what's higher may consum the event. + std::multimap::const_reverse_iterator + next_iterator; + size_t current_z_order; + }; + + // If the window is closed, the platform native window is either being + // destroyed, or doesn't exist anymore, and thus it's in a non-interactive + // state. + bool IsClosed() const { + return phase_ < Phase::kOpening && phase_ > Phase::kOpenBeforeClosing; + } + + bool CanApplyState() const { + // In kOpening, OpenImpl itself pulls the desired state itself and applies + // it, the Apply* functions can't be called and are unsafe to call because + // the implementation is an incomplete state, with the platform window + // potentially not existing. In kOpenBeforeClosing, as the native window + // still hasn't been destroyed and it can receive new state, still allowing + // applying new state for more consistency between the desired and the + // actual state during the final listener invocation. + return phase_ >= Phase::kOpen && phase_ <= Phase::kOpenBeforeClosing; + } + + bool CanSendEventsToListeners() const { + return phase_ >= Phase::kOpen && phase_ <= Phase::kOpenBeforeClosing; + } + // The listeners may delete the Window - check the destruction receiver after + // calling and stop doing anything accessing *this if that happens. + void SendEventToListeners(std::function fn, + WindowDestructionReceiver& destruction_receiver); + void PropagateEventThroughInputListeners( + std::function fn, + WindowDestructionReceiver& destruction_receiver); + + std::unique_ptr CreateSurface(Surface::TypeFlags allowed_types) { + // If opening, surface creation is deferred until all the initial setup has + // completed. Destruction of the surface is also a part of the closing + // process in OnBeforeClose. + if (phase_ != Phase::kOpen) { + return nullptr; + } + return CreateSurfaceImpl(allowed_types); + } WindowedAppContext& app_context_; - std::unique_ptr main_menu_; - std::string title_; -#ifdef XE_PLATFORM_GNU_LINUX - // GTK must have a default value here that isn't 0 - // TODO(Triang3l): Cleanup and unify this. May need to get the first resize - // message on various platforms. - int32_t width_ = 1280; - int32_t height_ = 720; -#else - int32_t width_ = 0; - int32_t height_ = 0; -#endif - bool has_focus_ = true; - bool is_cursor_visible_ = true; - bool is_imgui_input_enabled_ = false; - std::unique_ptr context_; - std::unique_ptr imgui_drawer_; - - uint32_t frame_count_ = 0; - uint32_t fps_ = 0; - uint64_t fps_update_time_ticks_ = 0; - uint64_t fps_frame_count_ = 0; - uint64_t last_paint_time_ticks_ = 0; - - bool modifier_shift_pressed_ = false; - bool modifier_cntrl_pressed_ = false; - bool modifier_alt_pressed_ = false; - bool modifier_super_pressed_ = false; + Phase phase_ = Phase::kClosedOpenable; + WindowDestructionReceiver* innermost_destruction_receiver_ = nullptr; // All currently-attached listeners that get event notifications. - bool in_listener_loop_ = false; std::vector listeners_; - std::vector pending_listener_attaches_; - std::vector pending_listener_detaches_; + // Ordered by the Z order, and then by the time of addition (but executed in + // reverse order). + // Note: All the iteration logic involving this Z ordering must be the same as + // in drawing (in the UI drawers in the Presenter), but in reverse. + std::multimap input_listeners_; + // Linked list-based stacks of the contexts of the listener iterations + // currently being done, usually allocated on the stack. + ListenerIterationContext* innermost_listener_iteration_context_ = nullptr; + InputListenerIterationContext* innermost_input_listener_iteration_context_ = + nullptr; + + uint32_t desired_logical_width_ = 0; + uint32_t desired_logical_height_ = 0; + // Set by the implementation via OnActualSizeUpdate (from OpenImpl or from the + // platform resize handler). + uint32_t actual_physical_width_ = 0; + uint32_t actual_physical_height_ = 0; + + bool fullscreen_ = false; + + std::string title_; + + std::unique_ptr main_menu_; + + uint32_t mouse_capture_request_count_ = 0; + + CursorVisibility cursor_visibility_ = CursorVisibility::kVisible; + + bool has_focus_ = false; + + Presenter* presenter_ = nullptr; + std::unique_ptr presenter_surface_; + // Whether currently in InPaint to prevent recursive painting in case it's + // triggered somehow from within painting again, because painting is much more + // complex than just a small state update, and recursive painting is + // completely unsupported by the Presenter. + bool is_painting_ = false; }; } // namespace ui diff --git a/src/xenia/ui/window_android.cc b/src/xenia/ui/window_android.cc index cd5aaba80..817f439c7 100644 --- a/src/xenia/ui/window_android.cc +++ b/src/xenia/ui/window_android.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,36 +13,120 @@ #include #include "xenia/base/assert.h" +#include "xenia/ui/surface_android.h" #include "xenia/ui/windowed_app_context_android.h" namespace xe { namespace ui { std::unique_ptr Window::Create(WindowedAppContext& app_context, - const std::string& title) { - // The window is a proxy between the main activity and Xenia, so there can be - // only one for an activity. - AndroidWindowedAppContext& android_app_context = - static_cast(app_context); - AndroidWindow* current_activity_window = - android_app_context.GetActivityWindow(); - assert_null(current_activity_window); - if (current_activity_window) { - return nullptr; - } - auto window = std::make_unique(app_context, title); - android_app_context.SetActivityWindow(window.get()); - return std::move(window); + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) { + return std::make_unique( + app_context, title, desired_logical_width, desired_logical_height); } AndroidWindow::~AndroidWindow() { - AndroidWindowedAppContext& android_app_context = + EnterDestructor(); + auto& android_app_context = static_cast(app_context()); if (android_app_context.GetActivityWindow() == this) { android_app_context.SetActivityWindow(nullptr); } } +void AndroidWindow::OnActivitySurfaceLayoutChange() { + auto& android_app_context = + static_cast(app_context()); + assert_true(android_app_context.GetActivityWindow() == this); + uint32_t physical_width = + uint32_t(android_app_context.window_surface_layout_right() - + android_app_context.window_surface_layout_left()); + uint32_t physical_height = + uint32_t(android_app_context.window_surface_layout_bottom() - + android_app_context.window_surface_layout_top()); + OnDesiredLogicalSizeUpdate(SizeToLogical(physical_width), + SizeToLogical(physical_height)); + WindowDestructionReceiver destruction_receiver(this); + OnActualSizeUpdate(physical_width, physical_height, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +uint32_t AndroidWindow::GetLatestDpiImpl() const { + auto& android_app_context = + static_cast(app_context()); + return android_app_context.GetPixelDensity(); +} + +bool AndroidWindow::OpenImpl() { + // The window is a proxy between the main activity and Xenia, so there can be + // only one open window for an activity. + auto& android_app_context = + static_cast(app_context()); + AndroidWindow* previous_activity_window = + android_app_context.GetActivityWindow(); + assert_null(previous_activity_window); + if (previous_activity_window) { + // Don't detach the old window as it's assuming it's still attached while + // it's in an open phase. + return false; + } + android_app_context.SetActivityWindow(this); + + // Report the initial layout. + OnActivitySurfaceLayoutChange(); + + return true; +} + +void AndroidWindow::RequestCloseImpl() { + // Finishing the Activity would cause the entire WindowedAppContext to quit, + // which is not the same behavior as on other platforms - the + // WindowedAppContext quit is done explicitly by the listeners during + // OnClosing if needed (the main Window is potentially being changed to a + // different one, for instance). Therefore, only detach the window from the + // app context. + + WindowDestructionReceiver destruction_receiver(this); + OnBeforeClose(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + OnAfterClose(); + + auto& android_app_context = + static_cast(app_context()); + if (android_app_context.GetActivityWindow() == this) { + android_app_context.SetActivityWindow(nullptr); + } +} + +std::unique_ptr AndroidWindow::CreateSurfaceImpl( + Surface::TypeFlags allowed_types) { + if (allowed_types & Surface::kTypeFlag_AndroidNativeWindow) { + auto& android_app_context = + static_cast(app_context()); + assert_true(android_app_context.GetActivityWindow() == this); + ANativeWindow* activity_window_surface = + android_app_context.GetWindowSurface(); + if (activity_window_surface) { + return std::make_unique( + activity_window_surface); + } + } + return nullptr; +} + +void AndroidWindow::RequestPaintImpl() { + auto& android_app_context = + static_cast(app_context()); + assert_true(android_app_context.GetActivityWindow() == this); + android_app_context.PostInvalidateWindowSurface(); +} + std::unique_ptr MenuItem::Create(Type type, const std::string& text, const std::string& hotkey, diff --git a/src/xenia/ui/window_android.h b/src/xenia/ui/window_android.h index 780c1d77d..52fac19ec 100644 --- a/src/xenia/ui/window_android.h +++ b/src/xenia/ui/window_android.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,31 +18,30 @@ namespace ui { class AndroidWindow : public Window { public: - // Many functions are left unimplemented because the layout is configured from - // XML and Java. + // Several state-related functions are left unimplemented because the layout + // is configured from XML and Java. - AndroidWindow(WindowedAppContext& app_context, const std::string& title) - : Window(app_context, title) {} + AndroidWindow(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height) + : Window(app_context, title, desired_logical_width, + desired_logical_height) {} ~AndroidWindow(); - NativePlatformHandle native_platform_handle() const override { - return nullptr; - } - // TODO(Triang3l): ANativeWindow for Vulkan surface creation. - NativeWindowHandle native_handle() const override { return nullptr; } + uint32_t GetMediumDpi() const override { return 160; } - void EnableMainMenu() override {} - void DisableMainMenu() override {} + void OnActivitySurfaceLayoutChange(); + void OnActivitySurfaceChanged() { OnSurfaceChanged(true); } + void PaintActivitySurface(bool force_paint) { OnPaint(force_paint); } - bool SetIcon(const void* buffer, size_t size) override { return false; } + protected: + uint32_t GetLatestDpiImpl() const override; - bool CaptureMouse() override { return false; } - bool ReleaseMouse() override { return false; } + bool OpenImpl() override; + void RequestCloseImpl() override; - int get_medium_dpi() const override { return 160; } - - // TODO(Triang3l): Call the close event, which may finish the activity. - void Close() override {} + std::unique_ptr CreateSurfaceImpl( + Surface::TypeFlags allowed_types) override; + void RequestPaintImpl() override; }; // Dummy for the menu item - menus are controlled by the layout. @@ -53,9 +52,6 @@ class AndroidMenuItem final : public MenuItem { AndroidMenuItem(Type type, const std::string& text, const std::string& hotkey, std::function callback) : MenuItem(type, text, hotkey, callback) {} - - void EnableMenuItem(Window& window) override {} - void DisableMenuItem(Window& window) override {} }; } // namespace ui diff --git a/src/xenia/ui/window_demo.cc b/src/xenia/ui/window_demo.cc index 727dbd33f..0d1e97a9a 100644 --- a/src/xenia/ui/window_demo.cc +++ b/src/xenia/ui/window_demo.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,6 +17,8 @@ #include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" #include "xenia/ui/window_demo.h" @@ -30,26 +32,31 @@ bool WindowDemoApp::OnInitialize() { Profiler::Initialize(); Profiler::ThreadEnter("Main"); - // Create graphics provider that provides the context for the window. + // Create the graphics provider that provides the presenter for the window. graphics_provider_ = CreateGraphicsProvider(); if (!graphics_provider_) { + XELOGE("Failed to initialize the graphics provider"); return false; } + enum : size_t { + kZOrderImGui, + kZOrderProfiler, + kZOrderWindowDemoInput, + }; + // Create the window. - window_ = xe::ui::Window::Create(app_context(), GetName()); - if (!window_->Initialize()) { - XELOGE("Failed to initialize main window"); - return false; - } + window_ = xe::ui::Window::Create(app_context(), GetName(), 1920, 1200); + window_->AddListener(&window_listener_); + window_->AddInputListener(&window_listener_, kZOrderWindowDemoInput); // Main menu. auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File"); { - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "&Close", - "Alt+F4", - [this]() { window_->Close(); })); + file_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "&Close", "Alt+F4", + [this]() { window_->RequestClose(); })); } main_menu->AddChild(std::move(file_menu)); auto debug_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Debug"); @@ -62,51 +69,61 @@ bool WindowDemoApp::OnInitialize() { []() { Profiler::TogglePause(); })); } main_menu->AddChild(std::move(debug_menu)); - window_->set_main_menu(std::move(main_menu)); + window_->SetMainMenu(std::move(main_menu)); - // Initial size setting, done here so that it knows the menu exists. - window_->Resize(1920, 1200); + // Open the window once it's configured. + if (!window_->Open()) { + XELOGE("Failed to open the main window"); + return false; + } - // Create the graphics context for the window. The window will finish - // initialization with the context (loading resources, etc). - window_->set_context(graphics_provider_->CreateHostContext(window_.get())); + // Setup drawing to the window. - // Setup the profiler display. - GraphicsContextLock context_lock(window_->context()); - Profiler::set_window(window_.get()); + presenter_ = graphics_provider_->CreatePresenter(); + if (!presenter_) { + XELOGE("Failed to initialize the presenter"); + return false; + } - // Enable imgui input. - window_->set_imgui_input_enabled(true); + immediate_drawer_ = graphics_provider_->CreateImmediateDrawer(); + if (!immediate_drawer_) { + XELOGE("Failed to initialize the immediate drawer"); + return false; + } + immediate_drawer_->SetPresenter(presenter_.get()); - window_->on_closed.AddListener([this](xe::ui::UIEvent* e) { - XELOGI("User-initiated death!"); - app_context().QuitFromUIThread(); - }); + imgui_drawer_ = std::make_unique(window_.get(), kZOrderImGui); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + immediate_drawer_.get()); + demo_dialog_ = std::make_unique(imgui_drawer_.get()); - window_->on_key_down.AddListener([](xe::ui::KeyEvent* e) { - switch (e->virtual_key()) { - case VirtualKey::kF3: - Profiler::ToggleDisplay(); - break; - default: - break; - } - }); + Profiler::SetUserIO(kZOrderProfiler, window_.get(), presenter_.get(), + immediate_drawer_.get()); - window_->on_painting.AddListener([this](xe::ui::UIEvent* e) { - auto& io = window_->imgui_drawer()->GetIO(); - - ImGui::ShowDemoWindow(); - ImGui::ShowMetricsWindow(); - - Profiler::Flip(); - - // Continuous paint. - window_->Invalidate(); - }); + window_->SetPresenter(presenter_.get()); return true; } +void WindowDemoApp::WindowDemoWindowListener::OnClosing(UIEvent& e) { + app_context_.QuitFromUIThread(); +} + +void WindowDemoApp::WindowDemoWindowListener::OnKeyDown(KeyEvent& e) { + switch (e.virtual_key()) { + case VirtualKey::kF3: + Profiler::ToggleDisplay(); + break; + default: + return; + } + e.set_handled(true); +} + +void WindowDemoApp::WindowDemoDialog::OnDraw(ImGuiIO& io) { + ImGui::ShowDemoWindow(); + ImGui::ShowMetricsWindow(); +} + } // namespace ui } // namespace xe diff --git a/src/xenia/ui/window_demo.h b/src/xenia/ui/window_demo.h index 29b6bc1fa..f3942ea7c 100644 --- a/src/xenia/ui/window_demo.h +++ b/src/xenia/ui/window_demo.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -14,7 +14,12 @@ #include #include "xenia/ui/graphics_provider.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" namespace xe { @@ -29,13 +34,41 @@ class WindowDemoApp : public WindowedApp { protected: explicit WindowDemoApp(WindowedAppContext& app_context, const std::string_view name) - : WindowedApp(app_context, name) {} + : WindowedApp(app_context, name), window_listener_(app_context) {} virtual std::unique_ptr CreateGraphicsProvider() const = 0; private: + class WindowDemoWindowListener final : public WindowListener, + public WindowInputListener { + public: + explicit WindowDemoWindowListener(WindowedAppContext& app_context) + : app_context_(app_context) {} + + void OnClosing(UIEvent& e) override; + + void OnKeyDown(KeyEvent& e) override; + + private: + WindowedAppContext& app_context_; + }; + + class WindowDemoDialog final : public ImGuiDialog { + public: + explicit WindowDemoDialog(ImGuiDrawer* imgui_drawer) + : ImGuiDialog(imgui_drawer) {} + + protected: + void OnDraw(ImGuiIO& io) override; + }; + + WindowDemoWindowListener window_listener_; std::unique_ptr graphics_provider_; std::unique_ptr window_; + std::unique_ptr presenter_; + std::unique_ptr immediate_drawer_; + std::unique_ptr imgui_drawer_; + std::unique_ptr demo_dialog_; }; } // namespace ui diff --git a/src/xenia/ui/window_gtk.cc b/src/xenia/ui/window_gtk.cc index b35f91305..6eb563667 100644 --- a/src/xenia/ui/window_gtk.cc +++ b/src/xenia/ui/window_gtk.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -11,11 +11,13 @@ #include #include +#include +#include #include "xenia/base/assert.h" -#include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/base/platform_linux.h" +#include "xenia/ui/surface_gnulinux.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window_gtk.h" @@ -23,384 +25,407 @@ namespace xe { namespace ui { std::unique_ptr Window::Create(WindowedAppContext& app_context, - const std::string& title) { - return std::make_unique(app_context, title); + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) { + return std::make_unique(app_context, title, desired_logical_width, + desired_logical_height); } -GTKWindow::GTKWindow(WindowedAppContext& app_context, const std::string& title) - : Window(app_context, title) {} +GTKWindow::GTKWindow(WindowedAppContext& app_context, + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) + : Window(app_context, title, desired_logical_width, + desired_logical_height) {} GTKWindow::~GTKWindow() { - OnDestroy(); + EnterDestructor(); if (window_) { - if (GTK_IS_WIDGET(window_)) { - gtk_widget_destroy(window_); - } + // Set window_ to null to ignore events from now on since this ui::GTKWindow + // is entering an indeterminate state. + GtkWidget* window = window_; window_ = nullptr; + // Destroying the top-level window also destroys its children. + drawing_area_ = nullptr; + box_ = nullptr; + gtk_widget_destroy(window); } } -bool GTKWindow::Initialize() { return OnCreate(); } - -gboolean gtk_event_handler(GtkWidget* widget, GdkEvent* event, gpointer data) { - GTKWindow* window = reinterpret_cast(data); - switch (event->type) { - case GDK_OWNER_CHANGE: - window->HandleWindowOwnerChange(&(event->owner_change)); - break; - case GDK_VISIBILITY_NOTIFY: - window->HandleWindowVisibility(&(event->visibility)); - break; - case GDK_KEY_PRESS: - case GDK_KEY_RELEASE: - window->HandleKeyboard(&(event->key)); - break; - case GDK_SCROLL: - case GDK_MOTION_NOTIFY: - case GDK_BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - window->HandleMouse(&(event->any)); - break; - case GDK_FOCUS_CHANGE: - window->HandleWindowFocus(&(event->focus_change)); - break; - case GDK_CONFIGURE: - // Only handle the event for the drawing area so we don't save - // a width and height that includes the menu bar on the full window - if (event->configure.window == - gtk_widget_get_window(window->drawing_area_)) { - window->HandleWindowResize(&(event->configure)); - } - break; - default: - // Do nothing - break; - } - // Propagate the event to other handlers - return GDK_EVENT_PROPAGATE; -} - -gboolean draw_callback(GtkWidget* widget, GdkFrameClock* frame_clock, - gpointer data) { - GTKWindow* window = reinterpret_cast(data); - window->HandleWindowPaint(); - return G_SOURCE_CONTINUE; -} - -gboolean close_callback(GtkWidget* widget, gpointer data) { - GTKWindow* window = reinterpret_cast(data); - window->Close(); - return G_SOURCE_CONTINUE; -} - -bool GTKWindow::OnCreate() { - // GTK optionally allows passing argv and argc here for parsing gtk specific - // options. We won't bother +bool GTKWindow::OpenImpl() { window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_resizable(GTK_WINDOW(window_), true); - gtk_window_set_title(GTK_WINDOW(window_), title_.c_str()); - gtk_window_set_default_size(GTK_WINDOW(window_), width_, height_); - // Drawing area is where we will attach our vulkan/gl context - drawing_area_ = gtk_drawing_area_new(); - // tick callback is for the refresh rate of the window - gtk_widget_add_tick_callback(drawing_area_, draw_callback, - reinterpret_cast(this), nullptr); - // Attach our event handler to both the main window (for keystrokes) and the - // drawing area (for mouse input, resize event, etc) - g_signal_connect(G_OBJECT(drawing_area_), "event", - G_CALLBACK(gtk_event_handler), - reinterpret_cast(this)); - GdkDisplay* gdk_display = gtk_widget_get_display(window_); - assert(GDK_IS_X11_DISPLAY(gdk_display)); - connection_ = XGetXCBConnection(gdk_x11_display_get_xdisplay(gdk_display)); + gtk_window_set_title(GTK_WINDOW(window_), GetTitle().c_str()); - g_signal_connect(G_OBJECT(window_), "event", G_CALLBACK(gtk_event_handler), - reinterpret_cast(this)); - // When the window manager kills the window (ie, the user hits X) - g_signal_connect(G_OBJECT(window_), "destroy", G_CALLBACK(close_callback), - reinterpret_cast(this)); - // Enable only keyboard events (so no mouse) for the top window - gtk_widget_set_events(window_, GDK_KEY_PRESS | GDK_KEY_RELEASE); - // Enable all events for the drawing area - gtk_widget_add_events(drawing_area_, GDK_ALL_EVENTS_MASK); - // Place the drawing area in a container (which later will hold the menu) - // then let it fill the whole area + // Create the vertical box container for the main menu and the drawing area. box_ = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - gtk_box_pack_end(GTK_BOX(box_), drawing_area_, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(window_), box_); + + // Add the main menu (even if fullscreen was requested, for the initial layout + // calculation). + const GTKMenuItem* main_menu = static_cast(GetMainMenu()); + GtkWidget* main_menu_widget = main_menu ? main_menu->handle() : nullptr; + if (main_menu_widget) { + gtk_box_pack_start(GTK_BOX(box_), main_menu_widget, FALSE, FALSE, 0); + } + + // Create the drawing area for creating the surface for, which will be the + // client area of the window occupying all the window space not taken by the + // main menu. + drawing_area_ = gtk_drawing_area_new(); + gtk_box_pack_end(GTK_BOX(box_), drawing_area_, TRUE, TRUE, 0); + // The desired size is the client (drawing) area size. Let GTK auto-size the + // entire window around it (as well as the width of the menu actually if it + // happens to be bigger - the desired size in the Window will be updated later + // to reflect that). + gtk_widget_set_size_request(drawing_area_, GetDesiredLogicalWidth(), + GetDesiredLogicalHeight()); + + // Attach the event handlers. + // Keyboard events are processed by the window, mouse events are processed + // within, and by, the drawing (client) area. + gtk_widget_set_events(window_, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | + GDK_FOCUS_CHANGE_MASK); + gtk_widget_set_events(drawing_area_, + GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_SCROLL_MASK); + g_signal_connect(G_OBJECT(window_), "event", + G_CALLBACK(WindowEventHandlerThunk), + reinterpret_cast(this)); + g_signal_connect(G_OBJECT(drawing_area_), "event", + G_CALLBACK(DrawingAreaEventHandlerThunk), + reinterpret_cast(this)); + g_signal_connect(G_OBJECT(drawing_area_), "draw", G_CALLBACK(DrawHandler), + reinterpret_cast(this)); + + // Finally show all the widgets in the window, including the main menu. gtk_widget_show_all(window_); - return super::OnCreate(); -} + // Remove the size request after finishing the initial layout because it makes + // it impossible to make the window smaller. + gtk_widget_set_size_request(drawing_area_, -1, -1); -void GTKWindow::OnDestroy() { super::OnDestroy(); } - -void GTKWindow::OnClose() { - if (!closing_ && window_) { - closing_ = true; + // After setting up the initial layout for non-fullscreen, enter fullscreen if + // requested. + if (IsFullscreen()) { + if (main_menu_widget) { + gtk_container_remove(GTK_CONTAINER(box_), main_menu_widget); + } + gtk_window_fullscreen(GTK_WINDOW(window_)); } - super::OnClose(); -} -bool GTKWindow::set_title(const std::string_view title) { - if (!super::set_title(title)) { - return false; + // Make sure the initial state after opening is reported to the common Window + // class no matter how GTK sends the events. + { + WindowDestructionReceiver destruction_receiver(this); + + // TODO(Triang3l): Report the desired client area size. + + GtkAllocation drawing_area_allocation; + gtk_widget_get_allocation(drawing_area_, &drawing_area_allocation); + OnActualSizeUpdate(uint32_t(drawing_area_allocation.width), + uint32_t(drawing_area_allocation.height), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return true; + } + + if (gtk_window_has_toplevel_focus(GTK_WINDOW(window_))) { + OnFocusUpdate(true, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return true; + } + } } - std::string titlez(title); - gtk_window_set_title(GTK_WINDOW(window_), (gchar*)titlez.c_str()); + return true; } -bool GTKWindow::SetIcon(const void* buffer, size_t size) { - // TODO(dougvj) Set icon after changin buffer to the correct format. (the - // call is gtk_window_set_icon) - return false; -} +void GTKWindow::RequestCloseImpl() { gtk_window_close(GTK_WINDOW(window_)); } -bool GTKWindow::is_fullscreen() const { return fullscreen_; } +void GTKWindow::ApplyNewFullscreen() { + // Various functions here may trigger events that may result in the listeners + // being invoked, and potentially cause the destruction of the window or + // fullscreen being toggled from inside this function. + WindowDestructionReceiver destruction_receiver(this); -void GTKWindow::ToggleFullscreen(bool fullscreen) { - if (fullscreen == is_fullscreen()) { - return; - } + const GTKMenuItem* main_menu = static_cast(GetMainMenu()); + GtkWidget* main_menu_widget = main_menu ? main_menu->handle() : nullptr; - fullscreen_ = fullscreen; - if (fullscreen) { + // Changing the menu and the fullscreen state may change the size of the + // drawing area too, don't handle the resize multiple times (also potentially + // with the listeners changing the desired fullscreen if called from the + // handling of some event like GDK_CONFIGURE). + BeginBatchedSizeUpdate(); + + if (IsFullscreen()) { + if (main_menu_widget) { + gtk_container_remove(GTK_CONTAINER(box_), main_menu_widget); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + } gtk_window_fullscreen(GTK_WINDOW(window_)); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } } else { gtk_window_unfullscreen(GTK_WINDOW(window_)); - } -} - -bool GTKWindow::is_bordered() const { - return gtk_window_get_decorated(GTK_WINDOW(window_)); -} - -void GTKWindow::set_bordered(bool enabled) { - if (is_fullscreen()) { - // Don't screw with the borders if we're fullscreen. - return; - } - gtk_window_set_decorated(GTK_WINDOW(window_), enabled); -} - -void GTKWindow::set_cursor_visible(bool value) { - if (is_cursor_visible_ == value) { - return; - } - if (value) { - // TODO(dougvj) Show and hide cursor - } else { - } -} - -void GTKWindow::set_focus(bool value) { - if (has_focus_ == value) { - return; - } - if (window_) { - if (value) { - gtk_window_activate_focus(GTK_WINDOW(window_)); - } else { - // TODO(dougvj) Check to see if we need to do something here to unset - // the focus. + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; } - } else { - has_focus_ = value; - } -} - -void GTKWindow::Resize(int32_t width, int32_t height) { - if (is_fullscreen()) { - // Cannot resize while in fullscreen. - return; - } - gtk_window_resize(GTK_WINDOW(window_), width, height); - super::Resize(width, height); -} - -void GTKWindow::Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) { - if (is_fullscreen()) { - // Cannot resize while in fullscreen. - return; - } - gtk_window_move(GTK_WINDOW(window_), left, top); - gtk_window_resize(GTK_WINDOW(window_), right - left, bottom - top); - super::Resize(left, top, right, bottom); -} - -void GTKWindow::OnResize(UIEvent* e) { super::OnResize(e); } - -void GTKWindow::Invalidate() { - // gtk_widget_queue_draw(drawing_area_); - super::Invalidate(); -} - -void GTKWindow::Close() { - if (closing_) { - return; - } - closing_ = true; - OnClose(); - gtk_widget_destroy(window_); - window_ = nullptr; -} - -void GTKWindow::OnMainMenuChange() { - // We need to store the old handle for detachment - static int count = 0; - auto main_menu = reinterpret_cast(main_menu_.get()); - if (main_menu && main_menu->handle()) { - if (!is_fullscreen()) { - gtk_box_pack_start(GTK_BOX(box_), main_menu->handle(), FALSE, FALSE, 0); - gtk_widget_show_all(window_); - } else { - gtk_container_remove(GTK_CONTAINER(box_), main_menu->handle()); + if (main_menu_widget) { + gtk_box_pack_start(GTK_BOX(box_), main_menu_widget, FALSE, FALSE, 0); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + // If the new menu is used for the first time, it will be in the hidden + // state initially. The menu might have been changed while in fullscreen + // without having shown it. + gtk_widget_show_all(main_menu_widget); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } } } -} -bool GTKWindow::HandleWindowOwnerChange(GdkEventOwnerChange* event) { - if (event->type == GDK_OWNER_CHANGE) { - if (event->reason == GDK_OWNER_CHANGE_DESTROY) { - OnDestroy(); - } else if (event->reason == GDK_OWNER_CHANGE_CLOSE) { - closing_ = true; - Close(); - OnClose(); - } - return true; + EndBatchedSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; } - return false; } -bool GTKWindow::HandleWindowPaint() { - auto e = UIEvent(this); - OnPaint(&e); - return true; +void GTKWindow::ApplyNewTitle() { + gtk_window_set_title(GTK_WINDOW(window_), GetTitle().c_str()); } -bool GTKWindow::HandleWindowResize(GdkEventConfigure* event) { - if (event->type == GDK_CONFIGURE) { - int32_t width = event->width; - int32_t height = event->height; - auto e = UIEvent(this); - if (width != width_ || height != height_) { - width_ = width; - height_ = height; - Layout(); - } - OnResize(&e); - return true; +void GTKWindow::ApplyNewMainMenu(MenuItem* old_main_menu) { + if (IsFullscreen()) { + // The menu will be set when exiting fullscreen. + return; } - return false; -} + // The fullscreen state may have been changed by some callback invoked, such + // as the configure (resize) one, recheck it after making changes also. -bool GTKWindow::HandleWindowVisibility(GdkEventVisibility* event) { - // TODO(dougvj) The gdk docs say that this is deprecated because modern window - // managers composite everything and nothing is truly hidden. - if (event->type == GDK_VISIBILITY_NOTIFY) { - if (event->state == GDK_VISIBILITY_UNOBSCURED) { - auto e = UIEvent(this); - OnVisible(&e); - } else { - auto e = UIEvent(this); - OnHidden(&e); + WindowDestructionReceiver destruction_receiver(this); + + // Changing the menu may change the size of the drawing area too, and here the + // menu may be changed twice (to detach the old one and to attach the new), + // don't handle the resize multiple times. + BeginBatchedSizeUpdate(); + + if (old_main_menu) { + const GTKMenuItem& old_gtk_main_menu = + *static_cast(old_main_menu); + gtk_container_remove(GTK_CONTAINER(box_), old_gtk_main_menu.handle()); + if (destruction_receiver.IsWindowDestroyedOrClosed() || IsFullscreen()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; } - return true; } - return false; -} -bool GTKWindow::HandleWindowFocus(GdkEventFocus* event) { - if (event->type == GDK_FOCUS_CHANGE) { - if (!event->in) { - has_focus_ = false; - auto e = UIEvent(this); - OnLostFocus(&e); - } else { - has_focus_ = true; - auto e = UIEvent(this); - OnGotFocus(&e); + const GTKMenuItem* new_main_menu = + static_cast(GetMainMenu()); + if (!new_main_menu) { + EndBatchedSizeUpdate(destruction_receiver); + return; + } + GtkWidget* new_main_menu_widget = new_main_menu->handle(); + gtk_box_pack_start(GTK_BOX(box_), new_main_menu_widget, FALSE, FALSE, 0); + if (destruction_receiver.IsWindowDestroyedOrClosed() || IsFullscreen()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); } - return true; + return; + } + // If the new menu is used for the first time, it will be in the hidden state + // initially. + gtk_widget_show_all(new_main_menu_widget); + if (destruction_receiver.IsWindowDestroyedOrClosed() || IsFullscreen()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + + EndBatchedSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; } - return false; } -bool GTKWindow::HandleMouse(GdkEventAny* event) { +void GTKWindow::FocusImpl() { gtk_window_activate_focus(GTK_WINDOW(window_)); } + +std::unique_ptr GTKWindow::CreateSurfaceImpl( + Surface::TypeFlags allowed_types) { + GdkDisplay* display = gtk_widget_get_display(window_); + GdkWindow* drawing_area_window = gtk_widget_get_window(drawing_area_); + bool type_known = false; + bool type_supported_by_display = false; + if (allowed_types & Surface::kTypeFlag_XcbWindow) { + type_known = true; + if (GDK_IS_X11_DISPLAY(display)) { + type_supported_by_display = true; + return std::make_unique( + XGetXCBConnection(gdk_x11_display_get_xdisplay(display)), + gdk_x11_window_get_xid(drawing_area_window)); + } + } + // TODO(Triang3l): Wayland surface. + if (type_known && !type_supported_by_display) { + XELOGE( + "GTKWindow: The window system of the GTK window is not supported by " + "Xenia"); + } + return nullptr; +} + +void GTKWindow::RequestPaintImpl() { gtk_widget_queue_draw(drawing_area_); } + +void GTKWindow::HandleSizeUpdate( + WindowDestructionReceiver& destruction_receiver) { + if (!drawing_area_) { + // Batched size update ended when the window has already been closed, for + // instance. + return; + } + + // TODO(Triang3l): Report the desired client area size. + + GtkAllocation drawing_area_allocation; + gtk_widget_get_allocation(drawing_area_, &drawing_area_allocation); + OnActualSizeUpdate(uint32_t(drawing_area_allocation.width), + uint32_t(drawing_area_allocation.height), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void GTKWindow::BeginBatchedSizeUpdate() { + // It's okay if batched_size_update_contained_* are not false when beginning + // a batched update, in case the new batched update was started by a window + // listener called from within EndBatchedSizeUpdate. + ++batched_size_update_depth_; +} + +void GTKWindow::EndBatchedSizeUpdate( + WindowDestructionReceiver& destruction_receiver) { + assert_not_zero(batched_size_update_depth_); + if (--batched_size_update_depth_) { + return; + } + // Resetting batched_size_update_contained_* in closing, not opening, because + // a listener may start a new batch, and finish it, and there won't be need to + // handle the deferred messages twice. + if (batched_size_update_contained_configure_) { + batched_size_update_contained_configure_ = false; + HandleSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + } + if (batched_size_update_contained_draw_) { + batched_size_update_contained_draw_ = false; + RequestPaint(); + } +} + +bool GTKWindow::HandleMouse(GdkEvent* event, + WindowDestructionReceiver& destruction_receiver) { MouseEvent::Button button = MouseEvent::Button::kNone; - int32_t dx = 0; - int32_t dy = 0; int32_t x = 0; int32_t y = 0; + int32_t scroll_x = 0; + int32_t scroll_y = 0; switch (event->type) { - default: - // Double click/etc? - return true; + case GDK_MOTION_NOTIFY: { + auto motion_event = reinterpret_cast(event); + x = motion_event->x; + y = motion_event->y; + } break; case GDK_BUTTON_PRESS: case GDK_BUTTON_RELEASE: { - GdkEventButton* e = reinterpret_cast(event); - switch (e->button) { + auto button_event = reinterpret_cast(event); + switch (button_event->button) { case 1: button = MouseEvent::Button::kLeft; break; - case 3: - button = MouseEvent::Button::kRight; - break; case 2: button = MouseEvent::Button::kMiddle; break; + case 3: + button = MouseEvent::Button::kRight; + break; case 4: button = MouseEvent::Button::kX1; break; case 5: button = MouseEvent::Button::kX2; break; + default: + // Still handle the movement. + break; } - x = e->x; - y = e->y; - break; - } - case GDK_MOTION_NOTIFY: { - GdkEventMotion* e = reinterpret_cast(event); - x = e->x; - y = e->y; - break; - } + x = button_event->x; + y = button_event->y; + } break; case GDK_SCROLL: { - GdkEventScroll* e = reinterpret_cast(event); - x = e->x; - y = e->y; - dx = e->delta_x; - dy = e->delta_y; - break; - } - } - - auto e = MouseEvent(this, button, x, y, dx, dy); - switch (event->type) { - case GDK_BUTTON_PRESS: - OnMouseDown(&e); - break; - case GDK_BUTTON_RELEASE: - OnMouseUp(&e); - break; - case GDK_MOTION_NOTIFY: - OnMouseMove(&e); - break; - case GDK_SCROLL: - OnMouseWheel(&e); - break; + auto scroll_event = reinterpret_cast(event); + x = scroll_event->x; + y = scroll_event->y; + scroll_x = scroll_event->delta_x * MouseEvent::kScrollPerDetent; + // In GDK, positive is towards the bottom of the screen, not forward from + // the user. + scroll_y = -scroll_event->delta_y * MouseEvent::kScrollPerDetent; + } break; default: return false; } + + MouseEvent e(this, button, x, y, scroll_x, scroll_y); + switch (event->type) { + case GDK_MOTION_NOTIFY: + OnMouseMove(e, destruction_receiver); + break; + case GDK_BUTTON_PRESS: + OnMouseDown(e, destruction_receiver); + break; + case GDK_BUTTON_RELEASE: + OnMouseUp(e, destruction_receiver); + break; + case GDK_SCROLL: + OnMouseWheel(e, destruction_receiver); + break; + default: + break; + } + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed(). return e.is_handled(); } -bool GTKWindow::HandleKeyboard(GdkEventKey* event) { +bool GTKWindow::HandleKeyboard( + GdkEventKey* event, WindowDestructionReceiver& destruction_receiver) { unsigned int modifiers = event->state; bool shift_pressed = modifiers & GDK_SHIFT_MASK; bool ctrl_pressed = modifiers & GDK_CONTROL_MASK; @@ -408,25 +433,154 @@ bool GTKWindow::HandleKeyboard(GdkEventKey* event) { bool super_pressed = modifiers & GDK_SUPER_MASK; uint32_t key_char = gdk_keyval_to_unicode(event->keyval); // TODO(Triang3l): event->hardware_keycode to VirtualKey translation. - auto e = KeyEvent(this, VirtualKey(event->hardware_keycode), 1, - event->type == GDK_KEY_RELEASE, shift_pressed, ctrl_pressed, - alt_pressed, super_pressed); + KeyEvent e(this, VirtualKey(event->hardware_keycode), 1, + event->type == GDK_KEY_RELEASE, shift_pressed, ctrl_pressed, + alt_pressed, super_pressed); switch (event->type) { case GDK_KEY_PRESS: - OnKeyDown(&e); + OnKeyDown(e, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return e.is_handled(); + } if (key_char > 0) { - OnKeyChar(&e); + OnKeyChar(e, destruction_receiver); } break; case GDK_KEY_RELEASE: - OnKeyUp(&e); + OnKeyUp(e, destruction_receiver); break; default: - return false; + break; } + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed(). return e.is_handled(); } +gboolean GTKWindow::WindowEventHandler(GdkEvent* event) { + switch (event->type) { + case GDK_DELETE: + // In case the widget was somehow forcibly destroyed without GDK_DELETE. + case GDK_DESTROY: { + WindowDestructionReceiver destruction_receiver(this); + OnBeforeClose(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + break; + } + // Set window_ to null to ignore events from now on since this + // ui::GTKWindow is entering an indeterminate state - this should be done + // at some point in closing anyway. + GtkWidget* window = window_; + window_ = nullptr; + // Destroying the top-level window also destroys its children. + drawing_area_ = nullptr; + box_ = nullptr; + if (event->type != GDK_DESTROY) { + gtk_widget_destroy(window); + } + OnAfterClose(); + } break; + + case GDK_FOCUS_CHANGE: { + auto focus_event = reinterpret_cast(event); + WindowDestructionReceiver destruction_receiver(this); + OnFocusUpdate(bool(focus_event->in), destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: { + WindowDestructionReceiver destruction_receiver(this); + HandleKeyboard(reinterpret_cast(event), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + default: + break; + } + + // The window might have been destroyed by the handlers, don't interact with + // *this in this function from now on. + + return GDK_EVENT_PROPAGATE; +} + +gboolean GTKWindow::WindowEventHandlerThunk(GtkWidget* widget, GdkEvent* event, + gpointer user_data) { + GTKWindow* window = reinterpret_cast(user_data); + if (!window || widget != window->window_ || + reinterpret_cast(event)->window != + gtk_widget_get_window(window->window_)) { + return GDK_EVENT_PROPAGATE; + } + return window->WindowEventHandler(event); +} + +gboolean GTKWindow::DrawingAreaEventHandler(GdkEvent* event) { + switch (event->type) { + case GDK_MOTION_NOTIFY: + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_SCROLL: { + WindowDestructionReceiver destruction_receiver(this); + HandleMouse(event, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + case GDK_CONFIGURE: { + if (batched_size_update_depth_) { + batched_size_update_contained_configure_ = true; + } else { + WindowDestructionReceiver destruction_receiver(this); + HandleSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } + } break; + default: + break; + } + + // The window might have been destroyed by the handlers, don't interact with + // *this in this function from now on. + + return GDK_EVENT_PROPAGATE; +} + +gboolean GTKWindow::DrawingAreaEventHandlerThunk(GtkWidget* widget, + GdkEvent* event, + gpointer user_data) { + GTKWindow* window = reinterpret_cast(user_data); + if (!window || widget != window->drawing_area_ || + reinterpret_cast(event)->window != + gtk_widget_get_window(window->drawing_area_)) { + return GDK_EVENT_PROPAGATE; + } + return window->DrawingAreaEventHandler(event); +} + +gboolean GTKWindow::DrawHandler(GtkWidget* widget, cairo_t* cr, + gpointer user_data) { + GTKWindow* window = reinterpret_cast(user_data); + if (!window || widget != window->drawing_area_) { + return FALSE; + } + if (window->batched_size_update_depth_) { + window->batched_size_update_contained_draw_ = true; + } else { + window->OnPaint(); + } + return TRUE; +} + std::unique_ptr MenuItem::Create(Type type, const std::string& text, const std::string& hotkey, @@ -434,17 +588,10 @@ std::unique_ptr MenuItem::Create(Type type, return std::make_unique(type, text, hotkey, callback); } -static void _menu_activate_callback(GtkWidget* gtk_menu, gpointer data) { - GTKMenuItem* menu = reinterpret_cast(data); - menu->Activate(); -} - -void GTKMenuItem::Activate() { - try { - callback_(); - } catch (const std::bad_function_call& e) { - // Ignore - } +void GTKMenuItem::ActivateHandler(GtkWidget* menu_item, gpointer user_data) { + static_cast(user_data)->OnSelected(); + // The menu item might have been destroyed by its OnSelected, don't do + // anything with it here from now on. } GTKMenuItem::GTKMenuItem(Type type, const std::string& text, @@ -475,13 +622,20 @@ GTKMenuItem::GTKMenuItem(Type type, const std::string& text, menu_ = gtk_menu_item_new_with_mnemonic(gtk_label); break; } - if (GTK_IS_MENU_ITEM(menu_)) - g_signal_connect(menu_, "activate", G_CALLBACK(_menu_activate_callback), - (gpointer)this); + if (menu_) { + // Own the object because it may be detached from and re-attached to a + // Window. + g_object_ref_sink(menu_); + if (GTK_IS_MENU_ITEM(menu_)) { + g_signal_connect(menu_, "activate", G_CALLBACK(ActivateHandler), + reinterpret_cast(this)); + } + } } GTKMenuItem::~GTKMenuItem() { if (menu_) { + g_object_unref(menu_); } } diff --git a/src/xenia/ui/window_gtk.h b/src/xenia/ui/window_gtk.h index 6677f2fc7..a78cae29f 100644 --- a/src/xenia/ui/window_gtk.h +++ b/src/xenia/ui/window_gtk.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -28,72 +28,61 @@ class GTKWindow : public Window { using super = Window; public: - GTKWindow(WindowedAppContext& app_context, const std::string& title); + GTKWindow(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height); ~GTKWindow() override; - NativePlatformHandle native_platform_handle() const override { - return connection_; - } - NativeWindowHandle native_handle() const override { return window_; } - GtkWidget* native_window_handle() const { return drawing_area_; } - - void EnableMainMenu() override {} - void DisableMainMenu() override {} - - bool set_title(const std::string_view title) override; - - bool SetIcon(const void* buffer, size_t size) override; - - // This seems to happen implicitly compared to Windows. - bool CaptureMouse() override { return true; }; - bool ReleaseMouse() override { return true; }; - - bool is_fullscreen() const override; - void ToggleFullscreen(bool fullscreen) override; - - bool is_bordered() const override; - void set_bordered(bool enabled) override; - - void set_cursor_visible(bool value) override; - void set_focus(bool value) override; - - void Resize(int32_t width, int32_t height) override; - void Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) override; - - bool Initialize() override; - void Invalidate() override; - void Close() override; + // Will be null if the window hasn't been successfully opened yet, or has been + // closed. + GtkWidget* window() const { return window_; } protected: - bool OnCreate() override; - void OnMainMenuChange() override; - void OnDestroy() override; - void OnClose() override; + bool OpenImpl() override; + void RequestCloseImpl() override; - void OnResize(UIEvent* e) override; + void ApplyNewFullscreen() override; + void ApplyNewTitle() override; + void ApplyNewMainMenu(MenuItem* old_main_menu) override; + // Mouse capture seems to happen implicitly compared to Windows. + void FocusImpl() override; + + std::unique_ptr CreateSurfaceImpl( + Surface::TypeFlags allowed_types) override; + void RequestPaintImpl() override; private: - GtkWidget* window_; - GtkWidget* box_; - GtkWidget* drawing_area_; - xcb_connection_t* connection_; + void HandleSizeUpdate(WindowDestructionReceiver& destruction_receiver); + // For updating multiple factors that may influence the window size at once, + // without handling the configure event multiple times (that may not only + // result in wasted handling, but also in the state potentially changed to an + // inconsistent one in the middle of a size update by the listeners). + void BeginBatchedSizeUpdate(); + void EndBatchedSizeUpdate(WindowDestructionReceiver& destruction_receiver); - // C Callback shims for GTK - friend gboolean gtk_event_handler(GtkWidget*, GdkEvent*, gpointer); - friend gboolean close_callback(GtkWidget*, gpointer); - friend gboolean draw_callback(GtkWidget*, GdkFrameClock*, gpointer); + // Handling events related to the whole window. + bool HandleMouse(GdkEvent* event, + WindowDestructionReceiver& destruction_receiver); + bool HandleKeyboard(GdkEventKey* event, + WindowDestructionReceiver& destruction_receiver); + gboolean WindowEventHandler(GdkEvent* event); + static gboolean WindowEventHandlerThunk(GtkWidget* widget, GdkEvent* event, + gpointer user_data); - bool HandleMouse(GdkEventAny* event); - bool HandleKeyboard(GdkEventKey* event); - bool HandleWindowResize(GdkEventConfigure* event); - bool HandleWindowFocus(GdkEventFocus* event); - bool HandleWindowVisibility(GdkEventVisibility* event); - bool HandleWindowOwnerChange(GdkEventOwnerChange* event); - bool HandleWindowPaint(); + // Handling events related specifically to the drawing (client) area. + gboolean DrawingAreaEventHandler(GdkEvent* event); + static gboolean DrawingAreaEventHandlerThunk(GtkWidget* widget, + GdkEvent* event, + gpointer user_data); + static gboolean DrawHandler(GtkWidget* widget, cairo_t* cr, gpointer data); - bool closing_ = false; - bool fullscreen_ = false; + // Non-owning (initially floating) references to the widgets. + GtkWidget* window_ = nullptr; + GtkWidget* box_ = nullptr; + GtkWidget* drawing_area_ = nullptr; + + uint32_t batched_size_update_depth_ = 0; + bool batched_size_update_contained_configure_ = false; + bool batched_size_update_contained_draw_ = false; }; class GTKMenuItem : public MenuItem { @@ -102,20 +91,16 @@ class GTKMenuItem : public MenuItem { std::function callback); ~GTKMenuItem() override; - GtkWidget* handle() { return menu_; } - using MenuItem::OnSelected; - void Activate(); - - void EnableMenuItem(Window& window) override {} - void DisableMenuItem(Window& window) override {} + GtkWidget* handle() const { return menu_; } protected: void OnChildAdded(MenuItem* child_item) override; void OnChildRemoved(MenuItem* child_item) override; - GTKMenuItem* parent_ = nullptr; - GTKMenuItem* child_ = nullptr; private: + static void ActivateHandler(GtkWidget* menu_item, gpointer user_data); + + // An owning reference because a menu may be transferred between windows. GtkWidget* menu_ = nullptr; }; diff --git a/src/xenia/ui/window_listener.h b/src/xenia/ui/window_listener.h index 08f7a5c7e..6dbf36c77 100644 --- a/src/xenia/ui/window_listener.h +++ b/src/xenia/ui/window_listener.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -15,38 +15,39 @@ namespace xe { namespace ui { -// Virtual interface for types that want to listen for Window events. -// Use Window::AttachListener and Window::DetachListener to manage active -// listeners. +// Virtual interfaces for types that want to listen for Window events. +// Use Window::Add[Input]Listener and Window::Remove[Input]Listener to manage +// active listeners. + class WindowListener { public: virtual ~WindowListener() = default; - virtual void OnMainMenuChange() {} - virtual void OnClosing(UIEvent* e) {} - virtual void OnClosed(UIEvent* e) {} + // OnOpened will be followed by various initial setup listeners. + virtual void OnOpened(UISetupEvent& e) {} + virtual void OnClosing(UIEvent& e) {} - virtual void OnResize(UIEvent* e) {} - virtual void OnLayout(UIEvent* e) {} - virtual void OnPainting(UIEvent* e) {} - virtual void OnPaint(UIEvent* e) {} - virtual void OnPainted(UIEvent* e) {} - virtual void OnFileDrop(UIEvent* e) {} + virtual void OnDpiChanged(UISetupEvent& e) {} + virtual void OnResize(UISetupEvent& e) {} - virtual void OnVisible(UIEvent* e) {} - virtual void OnHidden(UIEvent* e) {} + virtual void OnGotFocus(UISetupEvent& e) {} + virtual void OnLostFocus(UISetupEvent& e) {} - virtual void OnGotFocus(UIEvent* e) {} - virtual void OnLostFocus(UIEvent* e) {} + virtual void OnFileDrop(FileDropEvent& e) {} +}; - virtual void OnKeyDown(KeyEvent* e) {} - virtual void OnKeyUp(KeyEvent* e) {} - virtual void OnKeyChar(KeyEvent* e) {} +class WindowInputListener { + public: + virtual ~WindowInputListener() = default; - virtual void OnMouseDown(MouseEvent* e) {} - virtual void OnMouseMove(MouseEvent* e) {} - virtual void OnMouseUp(MouseEvent* e) {} - virtual void OnMouseWheel(MouseEvent* e) {} + virtual void OnKeyDown(KeyEvent& e) {} + virtual void OnKeyUp(KeyEvent& e) {} + virtual void OnKeyChar(KeyEvent& e) {} + + virtual void OnMouseDown(MouseEvent& e) {} + virtual void OnMouseMove(MouseEvent& e) {} + virtual void OnMouseUp(MouseEvent& e) {} + virtual void OnMouseWheel(MouseEvent& e) {} }; } // namespace ui diff --git a/src/xenia/ui/window_win.cc b/src/xenia/ui/window_win.cc index a6d2c68ae..39ea5b3da 100644 --- a/src/xenia/ui/window_win.cc +++ b/src/xenia/ui/window_win.cc @@ -2,71 +2,74 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/ui/window_win.h" -#include - +#include #include #include "xenia/base/assert.h" #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" +#include "xenia/ui/surface_win.h" + +// Must be included before Windows headers for things like NOMINMAX. #include "xenia/base/platform_win.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/windowed_app_context_win.h" +// For per-monitor DPI awareness v1. +#include + namespace xe { namespace ui { std::unique_ptr Window::Create(WindowedAppContext& app_context, - const std::string& title) { - return std::make_unique(app_context, title); + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) { + return std::make_unique( + app_context, title, desired_logical_width, desired_logical_height); } Win32Window::Win32Window(WindowedAppContext& app_context, - const std::string& title) - : Window(app_context, title) {} + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) + : Window(app_context, title, desired_logical_width, desired_logical_height), + arrow_cursor_(LoadCursor(nullptr, IDC_ARROW)) { + dpi_ = GetCurrentSystemDpi(); +} Win32Window::~Win32Window() { - OnDestroy(); + EnterDestructor(); + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } if (hwnd_) { - SetWindowLongPtr(hwnd_, GWLP_USERDATA, 0); - CloseWindow(hwnd_); + // Set hwnd_ to null to ignore events from now on since this Win32Window is + // entering an indeterminate state. + HWND hwnd = hwnd_; hwnd_ = nullptr; + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + DestroyWindow(hwnd); } if (icon_) { DestroyIcon(icon_); - icon_ = nullptr; } } -NativePlatformHandle Win32Window::native_platform_handle() const { - return static_cast(app_context()).hinstance(); -} +uint32_t Win32Window::GetMediumDpi() const { return USER_DEFAULT_SCREEN_DPI; } -bool Win32Window::Initialize() { return OnCreate(); } - -bool Win32Window::OnCreate() { - HINSTANCE hInstance = - static_cast(app_context()).hinstance(); - - // Per-monitor DPI awareness is expected to be enabled via the manifest, as - // that's the recommended way, which also doesn't require calling - // SetProcessDpiAwareness before doing anything that may depend on DPI - // awareness (so it's safe to use any Windows APIs before this code). - // TODO(Triang3l): Safe handling of per-monitor DPI awareness v2, with - // automatic scaling on DPI change. - if (!GetDpiForMonitor_) { - auto shcore = GetModuleHandleW(L"shcore.dll"); - if (shcore) { - GetDpiForMonitor_ = GetProcAddress(shcore, "GetDpiForMonitor"); - } - } +bool Win32Window::OpenImpl() { + const Win32WindowedAppContext& win32_app_context = + static_cast(app_context()); + HINSTANCE hinstance = win32_app_context.hinstance(); static bool has_registered_class = false; if (!has_registered_class) { @@ -76,11 +79,12 @@ bool Win32Window::OnCreate() { wcex.lpfnWndProc = Win32Window::WndProcThunk; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = LoadIconW(hInstance, L"MAINICON"); - wcex.hIconSm = NULL; // LoadIconW(hInstance, L"MAINICON"); - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hInstance = hinstance; + wcex.hIcon = LoadIconW(hinstance, L"MAINICON"); + wcex.hIconSm = nullptr; // LoadIconW(hinstance, L"MAINICON"); + wcex.hCursor = arrow_cursor_; + // Matches the black background color of the presenter's painting. + wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wcex.lpszMenuName = nullptr; wcex.lpszClassName = L"XeniaWindowClass"; if (!RegisterClassExW(&wcex)) { @@ -90,22 +94,92 @@ bool Win32Window::OnCreate() { has_registered_class = true; } - // Setup initial size. + const Win32MenuItem* main_menu = + static_cast(GetMainMenu()); + + // Setup the initial size for the non-fullscreen window. With per-monitor DPI, + // this is also done to be able to obtain the initial window rectangle (with + // CW_USEDEFAULT) to get the monitor for the window position, and then to + // adjust the normal window size to the new DPI. + // Save the initial desired size since it may be modified by the handler of + // the WM_SIZE sent during window creation - it's needed for the initial + // per-monitor DPI scaling. + uint32_t initial_desired_logical_width = GetDesiredLogicalWidth(); + uint32_t initial_desired_logical_height = GetDesiredLogicalHeight(); + const Win32WindowedAppContext::PerMonitorDpiV2Api* per_monitor_dpi_v2_api = + win32_app_context.per_monitor_dpi_v2_api(); + const Win32WindowedAppContext::PerMonitorDpiV1Api* per_monitor_dpi_v1_api = + win32_app_context.per_monitor_dpi_v1_api(); + // Even with per-monitor DPI, take the closest approximation (system DPI) to + // potentially more accurately determine the initial monitor. + dpi_ = GetCurrentSystemDpi(); DWORD window_style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; DWORD window_ex_style = WS_EX_APPWINDOW | WS_EX_CONTROLPARENT; - RECT rc = {0, 0, width_, height_}; - AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); - - // Create window. - hwnd_ = - CreateWindowExW(window_ex_style, L"XeniaWindowClass", - reinterpret_cast(xe::to_utf16(title_).c_str()), - window_style, rc.left, rc.top, rc.right - rc.left, - rc.bottom - rc.top, nullptr, nullptr, hInstance, this); + RECT window_size_rect; + window_size_rect.left = 0; + window_size_rect.top = 0; + window_size_rect.right = LONG(ConvertSizeDpi(initial_desired_logical_width, + dpi_, USER_DEFAULT_SCREEN_DPI)); + window_size_rect.bottom = LONG(ConvertSizeDpi(initial_desired_logical_height, + dpi_, USER_DEFAULT_SCREEN_DPI)); + AdjustWindowRectangle(window_size_rect, window_style, + BOOL(main_menu != nullptr), window_ex_style, dpi_); + // Create the window. Though WM_NCCREATE will assign to `hwnd_` too, still do + // the assignment here to handle the case of a failure after WM_NCCREATE, for + // instance. + hwnd_ = CreateWindowExW( + window_ex_style, L"XeniaWindowClass", + reinterpret_cast(xe::to_utf16(GetTitle()).c_str()), window_style, + CW_USEDEFAULT, CW_USEDEFAULT, + window_size_rect.right - window_size_rect.left, + window_size_rect.bottom - window_size_rect.top, nullptr, nullptr, + hinstance, this); if (!hwnd_) { - XELOGE("CreateWindow failed"); + XELOGE("CreateWindowExW failed"); return false; } + // For per-monitor DPI, obtain the DPI of the monitor the window was created + // on, and adjust the initial normal size for it. If as a result of this + // resizing, the window is moved to a different monitor, the WM_DPICHANGED + // handler will do the needed correction. + uint32_t initial_monitor_dpi = dpi_; + if (per_monitor_dpi_v2_api) { + initial_monitor_dpi = per_monitor_dpi_v2_api->get_dpi_for_window(hwnd_); + } else if (per_monitor_dpi_v1_api) { + HMONITOR monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST); + UINT monitor_dpi_x, monitor_dpi_y; + if (monitor && SUCCEEDED(per_monitor_dpi_v1_api->get_dpi_for_monitor( + monitor, MDT_DEFAULT, &monitor_dpi_x, &monitor_dpi_y))) { + initial_monitor_dpi = monitor_dpi_x; + } + } + if (dpi_ != initial_monitor_dpi) { + dpi_ = initial_monitor_dpi; + WINDOWPLACEMENT initial_dpi_placement; + // Note that WINDOWPLACEMENT contains workspace coordinates, which are + // adjusted to exclude toolbars such as the taskbar - the positions and + // rectangle origins there can't be mixed with origins of rectangles in + // virtual screen coordinates such as those involved in functions like + // GetWindowRect. + initial_dpi_placement.length = sizeof(initial_dpi_placement); + if (GetWindowPlacement(hwnd_, &initial_dpi_placement)) { + window_size_rect.left = 0; + window_size_rect.top = 0; + window_size_rect.right = LONG(ConvertSizeDpi( + initial_desired_logical_width, dpi_, USER_DEFAULT_SCREEN_DPI)); + window_size_rect.bottom = LONG(ConvertSizeDpi( + initial_desired_logical_height, dpi_, USER_DEFAULT_SCREEN_DPI)); + AdjustWindowRectangle(window_size_rect, window_style, + BOOL(main_menu != nullptr), window_ex_style, dpi_); + initial_dpi_placement.rcNormalPosition.right = + initial_dpi_placement.rcNormalPosition.left + + (window_size_rect.right - window_size_rect.left); + initial_dpi_placement.rcNormalPosition.bottom = + initial_dpi_placement.rcNormalPosition.top + + (window_size_rect.bottom - window_size_rect.top); + SetWindowPlacement(hwnd_, &initial_dpi_placement); + } + } // Disable flicks. ATOM atom = GlobalAddAtomW(L"MicrosoftTabletPenServiceProperty"); @@ -123,533 +197,617 @@ bool Win32Window::OnCreate() { reinterpret_cast(dwHwndTabletProperty)); GlobalDeleteAtom(atom); - // Enable DWM elevation. - EnableMMCSS(); // Enable file dragging from external sources DragAcceptFiles(hwnd_, true); - ShowWindow(hwnd_, SW_SHOWNORMAL); - UpdateWindow(hwnd_); + // Apply the initial state from the Window that the window shouldn't be + // visibly transitioned to. - arrow_cursor_ = LoadCursor(nullptr, IDC_ARROW); - - // Initial state. - if (!is_cursor_visible_) { - ShowCursor(FALSE); - } - if (has_focus_) { - SetFocus(hwnd_); - } - - return super::OnCreate(); -} - -void Win32Window::EnableMMCSS() { - HMODULE hLibrary = LoadLibraryW(L"DWMAPI.DLL"); - if (!hLibrary) { - return; - } - - typedef HRESULT(__stdcall * PDwmEnableMMCSS)(BOOL); - PDwmEnableMMCSS pDwmEnableMMCSS = - (PDwmEnableMMCSS)GetProcAddress(hLibrary, "DwmEnableMMCSS"); - if (pDwmEnableMMCSS) { - pDwmEnableMMCSS(TRUE); - } - - typedef HRESULT(__stdcall * PDwmSetPresentParameters)( - HWND, DWM_PRESENT_PARAMETERS*); - PDwmSetPresentParameters pDwmSetPresentParameters = - (PDwmSetPresentParameters)GetProcAddress(hLibrary, - "DwmSetPresentParameters"); - if (pDwmSetPresentParameters) { - DWM_PRESENT_PARAMETERS pp; - std::memset(&pp, 0, sizeof(DWM_PRESENT_PARAMETERS)); - pp.cbSize = sizeof(DWM_PRESENT_PARAMETERS); - pp.fQueue = FALSE; - pp.cBuffer = 2; - pp.fUseSourceRate = FALSE; - pp.cRefreshesPerFrame = 1; - pp.eSampling = DWM_SOURCE_FRAME_SAMPLING_POINT; - pDwmSetPresentParameters(hwnd_, &pp); - } - - FreeLibrary(hLibrary); -} - -void Win32Window::OnDestroy() { super::OnDestroy(); } - -void Win32Window::OnClose() { - if (!closing_ && hwnd_) { - closing_ = true; - } - super::OnClose(); -} - -void Win32Window::EnableMainMenu() { - if (main_menu_) { - main_menu_->EnableMenuItem(*this); - } -} - -void Win32Window::DisableMainMenu() { - if (main_menu_) { - main_menu_->DisableMenuItem(*this); - } -} - -bool Win32Window::set_title(const std::string_view title) { - if (!super::set_title(title)) { - return false; - } - auto wide_title = xe::to_utf16(title); - SetWindowTextW(hwnd_, reinterpret_cast(wide_title.c_str())); - return true; -} - -bool Win32Window::SetIcon(const void* buffer, size_t size) { - if (icon_ != nullptr) { - DestroyIcon(icon_); - icon_ = nullptr; - } - - // Reset icon to default. - auto default_icon = LoadIconW( - static_cast(app_context()).hinstance(), - L"MAINICON"); - SendMessageW(hwnd_, WM_SETICON, ICON_BIG, - reinterpret_cast(default_icon)); - SendMessageW(hwnd_, WM_SETICON, ICON_SMALL, - reinterpret_cast(default_icon)); - if (!buffer || !size) { - return true; - } - - // Create icon and set on window (if it's valid). - icon_ = CreateIconFromResourceEx( - reinterpret_cast(const_cast(buffer)), - static_cast(size), TRUE, 0x00030000, 0, 0, - LR_DEFAULTCOLOR | LR_DEFAULTSIZE); if (icon_) { SendMessageW(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast(icon_)); SendMessageW(hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast(icon_)); } - return false; -} - -bool Win32Window::CaptureMouse() { - if (GetCapture() != nullptr) { - return false; + if (IsFullscreen()) { + // Go fullscreen after setting up everything related to the placement of the + // non-fullscreen window. + WindowDestructionReceiver destruction_receiver(this); + ApplyFullscreenEntry(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return true; + } + } else { + if (main_menu) { + SetMenu(hwnd_, main_menu->handle()); + } } - SetCapture(hwnd_); + + // Finally show the window. + ShowWindow(hwnd_, SW_SHOWNORMAL); + + // Report the initial actual state after opening, messages for which might + // have missed if they were processed during CreateWindowExW when the HWND was + // not yet attached to the Win32Window. + { + WindowDestructionReceiver destruction_receiver(this); + + // Report the desired logical size of the client area in the non-maximized + // state after the initial layout setup in Windows. + WINDOWPLACEMENT shown_placement; + shown_placement.length = sizeof(shown_placement); + if (GetWindowPlacement(hwnd_, &shown_placement)) { + // Get the size of the non-client area to subtract it from the size of the + // entire window in its non-maximized state, to get the client area. + RECT non_client_area_rect = {}; + AdjustWindowRectangle(non_client_area_rect); + OnDesiredLogicalSizeUpdate( + SizeToLogical(uint32_t( + (shown_placement.rcNormalPosition.right - + shown_placement.rcNormalPosition.left) - + (non_client_area_rect.right - non_client_area_rect.left))), + SizeToLogical(uint32_t( + (shown_placement.rcNormalPosition.bottom - + shown_placement.rcNormalPosition.top) - + (non_client_area_rect.bottom - non_client_area_rect.top)))); + } + + // Report the actual physical size in the current state. + RECT shown_client_rect; + if (GetClientRect(hwnd_, &shown_client_rect)) { + OnActualSizeUpdate( + uint32_t(shown_client_rect.right - shown_client_rect.left), + uint32_t(shown_client_rect.bottom - shown_client_rect.top), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return true; + } + } + + OnFocusUpdate(GetFocus() == hwnd_, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return true; + } + } + + // Apply the initial state from the Window that involves interaction with the + // user. + + if (IsMouseCaptureRequested()) { + SetCapture(hwnd_); + } + + cursor_currently_auto_hidden_ = false; + CursorVisibility cursor_visibility = GetCursorVisibility(); + if (cursor_visibility != CursorVisibility::kVisible) { + if (cursor_visibility == CursorVisibility::kAutoHidden) { + if (!GetCursorPos(&cursor_auto_hide_last_screen_pos_)) { + cursor_auto_hide_last_screen_pos_.x = LONG_MAX; + cursor_auto_hide_last_screen_pos_.y = LONG_MAX; + } + cursor_currently_auto_hidden_ = true; + } + // OnFocusUpdate needs to be done before this. + SetCursorIfFocusedOnClientArea(nullptr); + } + return true; } -bool Win32Window::ReleaseMouse() { - if (GetCapture() != hwnd_) { - return false; - } - return ReleaseCapture() != 0; +void Win32Window::RequestCloseImpl() { + // Note that CloseWindow doesn't close the window, rather, it only minimizes + // it - need to send WM_CLOSE to let the Win32Window WndProc perform all the + // shutdown. + SendMessageW(hwnd_, WM_CLOSE, 0, 0); + // The window might have been deleted by the close handler, don't do anything + // with *this anymore (if that's needed, use a WindowDestructionReceiver). } -bool Win32Window::is_fullscreen() const { return fullscreen_; } +uint32_t Win32Window::GetLatestDpiImpl() const { + // hwnd_ may be null in this function, but the latest DPI is stored in a + // variable anyway. + return dpi_; +} -void Win32Window::ToggleFullscreen(bool fullscreen) { - if (fullscreen == is_fullscreen()) { - return; - } - - DWORD style = GetWindowLong(hwnd_, GWL_STYLE); - if (fullscreen) { - // https://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx - MONITORINFO mi = {sizeof(mi)}; - if (GetWindowPlacement(hwnd_, &windowed_pos_) && - GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY), - &mi)) { - // Remove the menubar and borders. - SetWindowLong(hwnd_, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); - ::SetMenu(hwnd_, NULL); - - // Resize the window to fullscreen. - auto& rc = mi.rcMonitor; - AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), false); - MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - TRUE); +void Win32Window::ApplyNewFullscreen() { + // Various functions here may send messages that may result in the + // listeners being invoked, and potentially cause the destruction of the + // window or fullscreen being toggled from inside this function. + WindowDestructionReceiver destruction_receiver(this); + if (IsFullscreen()) { + ApplyFullscreenEntry(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; } } else { - // Reinstate borders, resize to 1280x720 - SetWindowLong(hwnd_, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); - SetWindowPlacement(hwnd_, &windowed_pos_); + // Changing the style and the menu may change the size too, don't handle + // the resize multiple times (also potentially with the listeners changing + // the desired fullscreen if called from the handling of some message like + // WM_SIZE). + BeginBatchedSizeUpdate(); - auto main_menu = reinterpret_cast(main_menu_.get()); + // Reinstate the non-client area. + SetWindowLong(hwnd_, GWL_STYLE, + GetWindowLong(hwnd_, GWL_STYLE) | WS_OVERLAPPEDWINDOW); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + const Win32MenuItem* main_menu = + static_cast(GetMainMenu()); if (main_menu) { - ::SetMenu(hwnd_, main_menu->handle()); - } - } - - fullscreen_ = fullscreen; - - // width_ and height_ will be updated by the WM_SIZE handler - - // windowed_pos_.rcNormalPosition is also not the correct source for them when - // switching from fullscreen to maximized. -} - -bool Win32Window::is_bordered() const { - DWORD style = GetWindowLong(hwnd_, GWL_STYLE); - return (style & WS_OVERLAPPEDWINDOW) == WS_OVERLAPPEDWINDOW; -} - -void Win32Window::set_bordered(bool enabled) { - if (is_fullscreen()) { - // Don't screw with the borders if we're fullscreen. - return; - } - - DWORD style = GetWindowLong(hwnd_, GWL_STYLE); - if (enabled) { - SetWindowLong(hwnd_, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); - } else { - SetWindowLong(hwnd_, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); - } -} - -int Win32Window::get_dpi() const { - // TODO(Triang3l): Cache until WM_DPICHANGED is received (which, with - // per-monitor awareness v2 will also receive the new suggested window size). - // According to MSDN, x and y are identical. - - if (!GetDpiForMonitor_) { - HDC screen_hdc = GetDC(nullptr); - if (!screen_hdc) { - return get_medium_dpi(); - } - int logical_pixels_x = GetDeviceCaps(screen_hdc, LOGPIXELSX); - ReleaseDC(nullptr, screen_hdc); - return logical_pixels_x; - } - - HMONITOR monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY); - - UINT dpi_x, dpi_y; - auto gdfm = (decltype(&GetDpiForMonitor))GetDpiForMonitor_; - gdfm(monitor, MDT_DEFAULT, &dpi_x, &dpi_y); - return dpi_x; -} - -void Win32Window::set_cursor_visible(bool value) { - if (is_cursor_visible_ == value) { - return; - } - is_cursor_visible_ = value; - - if (value) { - ShowCursor(TRUE); - } else { - ShowCursor(FALSE); - } -} - -void Win32Window::set_focus(bool value) { - if (has_focus_ == value) { - return; - } - if (hwnd_) { - if (value) { - SetFocus(hwnd_); - } else { - SetFocus(nullptr); - } - } else { - has_focus_ = value; - } -} - -void Win32Window::Resize(int32_t width, int32_t height) { - if (is_fullscreen()) { - // Cannot resize while in fullscreen. - return; - } - - // Scale width and height - int32_t scaled_width, scaled_height; - float dpi_scale = get_dpi_scale(); - scaled_width = int32_t(width * dpi_scale); - scaled_height = int32_t(height * dpi_scale); - - RECT rc = {0, 0, 0, 0}; - GetWindowRect(hwnd_, &rc); - if (rc.top < 0) { - rc.top = 100; - } - if (rc.left < 0) { - rc.left = 100; - } - - rc.right = rc.left + scaled_width; - rc.bottom = rc.top + scaled_height; - - bool has_menu = !is_fullscreen() && (main_menu_ ? true : false); - AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu); - MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - TRUE); - - super::Resize(width, height); -} - -void Win32Window::Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) { - if (is_fullscreen()) { - // Cannot resize while in fullscreen. - return; - } - - RECT rc = {left, top, right, bottom}; - - // Scale width and height - float dpi_scale = get_dpi_scale(); - rc.right = int32_t((right - left) * dpi_scale) + left; - rc.bottom = int32_t((bottom - top) * dpi_scale) + top; - - bool has_menu = !is_fullscreen() && (main_menu_ ? true : false); - AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu); - MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - TRUE); - - super::Resize(left, top, right, bottom); -} - -void Win32Window::RawReposition(const RECT& rc) { - MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - TRUE); -} - -void Win32Window::OnResize(UIEvent* e) { - RECT client_rect; - GetClientRect(hwnd_, &client_rect); - int32_t width = client_rect.right - client_rect.left; - int32_t height = client_rect.bottom - client_rect.top; - - // Rescale to base DPI. - float dpi_scale = get_dpi_scale(); - width = int32_t(width / dpi_scale); - height = int32_t(height / dpi_scale); - - if (width != width_ || height != height_) { - width_ = width; - height_ = height; - Layout(); - } - super::OnResize(e); -} - -void Win32Window::Invalidate() { - super::Invalidate(); - InvalidateRect(hwnd_, nullptr, FALSE); -} - -void Win32Window::Close() { - if (closing_) { - return; - } - closing_ = true; - OnClose(); - DestroyWindow(hwnd_); - hwnd_ = nullptr; -} - -void Win32Window::OnMainMenuChange() { - auto main_menu = reinterpret_cast(main_menu_.get()); - // Don't actually set the menu if we're fullscreen. We'll do that later. - if (main_menu && !is_fullscreen()) { - ::SetMenu(hwnd_, main_menu->handle()); - } -} - -LRESULT CALLBACK Win32Window::WndProcThunk(HWND hWnd, UINT message, - WPARAM wParam, LPARAM lParam) { - Win32Window* window = nullptr; - if (message == WM_NCCREATE) { - auto create_struct = reinterpret_cast(lParam); - window = reinterpret_cast(create_struct->lpCreateParams); - SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)window); - } else { - window = - reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); - } - if (window) { - return window->WndProc(hWnd, message, wParam, lParam); - } else { - return DefWindowProc(hWnd, message, wParam, lParam); - } -} - -LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, - LPARAM lParam) { - if (hwnd_ != nullptr && hWnd != hwnd_) { - return DefWindowProc(hWnd, message, wParam, lParam); - } - - if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) { - if (HandleMouse(message, wParam, lParam)) { - return 0; - } else { - return DefWindowProc(hWnd, message, wParam, lParam); - } - } else if (message >= WM_KEYFIRST && message <= WM_KEYLAST) { - if (HandleKeyboard(message, wParam, lParam)) { - return 0; - } else { - return DefWindowProc(hWnd, message, wParam, lParam); - } - } - - switch (message) { - case WM_DROPFILES: { - HDROP drop_handle = reinterpret_cast(wParam); - auto drop_count = DragQueryFileW(drop_handle, 0xFFFFFFFFu, nullptr, 0); - if (drop_count > 0) { - // Get required buffer size - UINT path_size = DragQueryFileW(drop_handle, 0, nullptr, 0); - if (path_size > 0 && path_size < 0xFFFFFFFFu) { - std::u16string path; - ++path_size; // Ensure space for the null terminator - path.resize(path_size); // Reserve space - // Only getting first file dropped (other files ignored) - path_size = - DragQueryFileW(drop_handle, 0, (LPWSTR)&path[0], path_size); - if (path_size > 0) { - path.resize(path_size); // Will drop the null terminator - auto e = FileDropEvent(this, xe::to_path(path)); - OnFileDrop(&e); - } + SetMenu(hwnd_, main_menu->handle()); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); } + return; } - DragFinish(drop_handle); - } break; - case WM_NCCREATE: { - // Tell Windows to automatically scale non-client areas on different DPIs. - auto en = (BOOL(WINAPI*)(HWND hwnd))GetProcAddress( - GetModuleHandleW(L"user32.dll"), "EnableNonClientDpiScaling"); - if (en) { - en(hWnd); - } - } break; - case WM_CREATE: - break; - case WM_DESTROY: - OnDestroy(); - break; - case WM_CLOSE: - OnClose(); - break; - - case WM_MOVING: - break; - case WM_MOVE: - break; - case WM_SIZING: - break; - case WM_SIZE: { - auto e = UIEvent(this); - OnResize(&e); - } break; - - case WM_PAINT: { - ValidateRect(hwnd_, nullptr); - static bool in_paint = false; - if (!in_paint) { - in_paint = true; - auto e = UIEvent(this); - OnPaint(&e); - in_paint = false; - } - return 0; // Ignored because of custom paint. - } - case WM_ERASEBKGND: - return 0; // Ignored because of custom paint. - case WM_DISPLAYCHANGE: - break; - case WM_DPICHANGED: { - LPRECT rect = (LPRECT)lParam; - if (rect) { - RawReposition(*rect); - } - - auto e = UIEvent(this); - OnDpiChanged(&e); - } break; - - case WM_ACTIVATEAPP: - case WM_SHOWWINDOW: { - if (wParam == TRUE) { - auto e = UIEvent(this); - OnVisible(&e); - } else { - auto e = UIEvent(this); - OnHidden(&e); - } - break; } - case WM_KILLFOCUS: { - has_focus_ = false; - auto e = UIEvent(this); - OnLostFocus(&e); - break; + // For some reason, WM_DPICHANGED is not sent when the window is borderless + // fullscreen with per-monitor DPI awareness v1 (on Windows versions since + // Windows 8.1 before Windows 10 1703) - refresh the current DPI explicitly. + dpi_ = GetCurrentDpi(); + if (dpi_ != pre_fullscreen_dpi_) { + // Rescale the pre-fullscreen non-maximized window size to the new DPI as + // WM_DPICHANGED with the new rectangle was received for the fullscreen + // window size, not the windowed one. Simulating the behavior of the + // automatic resizing when changing the scale in the Windows settings (as + // of Windows 11 21H2 at least), which keeps the physical top-left origin + // of the entire window including the non-client area, but rescales the + // size. + // Note that WINDOWPLACEMENT contains workspace coordinates, which are + // adjusted to exclude toolbars such as the taskbar - the positions and + // rectangle origins there can't be mixed with origins of rectangles in + // virtual screen coordinates such as those involved in functions like + // GetWindowRect. + RECT new_dpi_rect; + new_dpi_rect.left = 0; + new_dpi_rect.top = 0; + new_dpi_rect.right = LONG(ConvertSizeDpi( + pre_fullscreen_normal_client_width_, dpi_, pre_fullscreen_dpi_)); + new_dpi_rect.bottom = LONG(ConvertSizeDpi( + pre_fullscreen_normal_client_height_, dpi_, pre_fullscreen_dpi_)); + AdjustWindowRectangle(new_dpi_rect); + pre_fullscreen_placement_.rcNormalPosition.right = + pre_fullscreen_placement_.rcNormalPosition.left + + (new_dpi_rect.right - new_dpi_rect.left); + pre_fullscreen_placement_.rcNormalPosition.bottom = + pre_fullscreen_placement_.rcNormalPosition.top + + (new_dpi_rect.bottom - new_dpi_rect.top); } - case WM_SETFOCUS: { - has_focus_ = true; - auto e = UIEvent(this); - OnGotFocus(&e); - break; + SetWindowPlacement(hwnd_, &pre_fullscreen_placement_); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; } - case WM_TABLET_QUERYSYSTEMGESTURESTATUS: - return - // disables press and hold (right-click) gesture - TABLET_DISABLE_PRESSANDHOLD | - // disables UI feedback on pen up (waves) - TABLET_DISABLE_PENTAPFEEDBACK | - // disables UI feedback on pen button down (circle) - TABLET_DISABLE_PENBARRELFEEDBACK | - // disables pen flicks (back, forward, drag down, drag up) - TABLET_DISABLE_FLICKS | TABLET_DISABLE_TOUCHSWITCH | - TABLET_DISABLE_SMOOTHSCROLLING | TABLET_DISABLE_TOUCHUIFORCEON | - TABLET_ENABLE_MULTITOUCHDATA; + // https://devblogs.microsoft.com/oldnewthing/20131017-00/?p=2903 + SetWindowPos(hwnd_, nullptr, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | + SWP_FRAMECHANGED); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } - case WM_MENUCOMMAND: { - // TODO(benvanik): Redirect this to MenuItem's on_selected delegate. - MENUINFO menu_info = {0}; - menu_info.cbSize = sizeof(menu_info); - menu_info.fMask = MIM_MENUDATA; - GetMenuInfo(HMENU(lParam), &menu_info); - auto parent_item = reinterpret_cast(menu_info.dwMenuData); - auto child_item = - reinterpret_cast(parent_item->child(wParam)); - assert_not_null(child_item); - UIEvent e(this); - child_item->OnSelected(&e); - } break; + EndBatchedSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } } - - return DefWindowProc(hWnd, message, wParam, lParam); } -bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) { - int32_t x = GET_X_LPARAM(lParam); - int32_t y = GET_Y_LPARAM(lParam); - if (message == WM_MOUSEWHEEL) { - POINT pt = {x, y}; - ScreenToClient(hwnd_, &pt); - x = pt.x; - y = pt.y; +void Win32Window::ApplyNewTitle() { + SetWindowTextW(hwnd_, + reinterpret_cast(xe::to_utf16(GetTitle()).c_str())); +} + +void Win32Window::LoadAndApplyIcon(const void* buffer, size_t size, + bool can_apply_state_in_current_phase) { + bool reset = !buffer || !size; + + HICON new_icon, new_icon_small; + if (reset) { + if (!icon_) { + // The icon is already the default one. + return; + } + if (!hwnd_) { + // Don't need to get the actual icon from the class if there's nothing to + // set it for yet (and there's no HWND to get it from, and the class may + // have not been registered yet also). + DestroyIcon(icon_); + icon_ = nullptr; + return; + } + new_icon = reinterpret_cast(GetClassLongPtrW(hwnd_, GCLP_HICON)); + new_icon_small = + reinterpret_cast(GetClassLongPtrW(hwnd_, GCLP_HICONSM)); + // Not caring if it's null in the class, accepting anything the class + // specifies. + } else { + new_icon = CreateIconFromResourceEx( + static_cast(const_cast(buffer)), DWORD(size), TRUE, + 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + if (!new_icon) { + return; + } + new_icon_small = new_icon; + } + + if (hwnd_) { + SendMessageW(hwnd_, WM_SETICON, ICON_BIG, + reinterpret_cast(new_icon)); + SendMessageW(hwnd_, WM_SETICON, ICON_SMALL, + reinterpret_cast(new_icon_small)); + } + + // The old icon is not in use anymore, safe to destroy it now. + if (icon_) { + DestroyIcon(icon_); + icon_ = nullptr; + } + + if (!reset) { + assert_true(new_icon_small == new_icon); + icon_ = new_icon; + } +} + +void Win32Window::ApplyNewMainMenu(MenuItem* old_main_menu) { + if (IsFullscreen()) { + // The menu will be set when exiting fullscreen. + return; + } + const Win32MenuItem* main_menu = + static_cast(GetMainMenu()); + WindowDestructionReceiver destruction_receiver(this); + SetMenu(hwnd_, main_menu ? main_menu->handle() : nullptr); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void Win32Window::CompleteMainMenuItemsUpdateImpl() { + if (IsFullscreen()) { + return; + } + DrawMenuBar(hwnd_); +} + +void Win32Window::ApplyNewMouseCapture() { + WindowDestructionReceiver destruction_receiver(this); + SetCapture(hwnd_); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void Win32Window::ApplyNewMouseRelease() { + if (GetCapture() != hwnd_) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ReleaseCapture(); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void Win32Window::ApplyNewCursorVisibility( + CursorVisibility old_cursor_visibility) { + CursorVisibility new_cursor_visibility = GetCursorVisibility(); + cursor_currently_auto_hidden_ = false; + if (new_cursor_visibility == CursorVisibility::kAutoHidden) { + if (!GetCursorPos(&cursor_auto_hide_last_screen_pos_)) { + cursor_auto_hide_last_screen_pos_.x = LONG_MAX; + cursor_auto_hide_last_screen_pos_.y = LONG_MAX; + } + cursor_currently_auto_hidden_ = true; + } else if (old_cursor_visibility == CursorVisibility::kAutoHidden) { + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } + } + SetCursorIfFocusedOnClientArea( + new_cursor_visibility == CursorVisibility::kVisible ? arrow_cursor_ + : nullptr); +} + +void Win32Window::FocusImpl() { SetFocus(hwnd_); } + +std::unique_ptr Win32Window::CreateSurfaceImpl( + Surface::TypeFlags allowed_types) { + HINSTANCE hInstance = + static_cast(app_context()).hinstance(); + if (allowed_types & Surface::kTypeFlag_Win32Hwnd) { + return std::make_unique(hInstance, hwnd_); + } + return nullptr; +} + +void Win32Window::RequestPaintImpl() { InvalidateRect(hwnd_, nullptr, FALSE); } + +BOOL Win32Window::AdjustWindowRectangle(RECT& rect, DWORD style, BOOL menu, + DWORD ex_style, UINT dpi) const { + const Win32WindowedAppContext& win32_app_context = + static_cast(app_context()); + const Win32WindowedAppContext::PerMonitorDpiV2Api* per_monitor_dpi_v2_api = + win32_app_context.per_monitor_dpi_v2_api(); + if (per_monitor_dpi_v2_api) { + return per_monitor_dpi_v2_api->adjust_window_rect_ex_for_dpi( + &rect, style, menu, ex_style, dpi); + } + // Before per-monitor DPI v2, there was no rescaling of the non-client + // area at runtime at all, so throughout the execution of the process it will + // behave the same regardless of the DPI. + return AdjustWindowRectEx(&rect, style, menu, ex_style); +} + +BOOL Win32Window::AdjustWindowRectangle(RECT& rect) const { + if (!hwnd_) { + return FALSE; + } + return AdjustWindowRectangle(rect, GetWindowLong(hwnd_, GWL_STYLE), + BOOL(GetMainMenu() != nullptr), + GetWindowLong(hwnd_, GWL_EXSTYLE), dpi_); +} + +uint32_t Win32Window::GetCurrentSystemDpi() const { + const Win32WindowedAppContext& win32_app_context = + static_cast(app_context()); + const Win32WindowedAppContext::PerMonitorDpiV2Api* per_monitor_dpi_v2_api = + win32_app_context.per_monitor_dpi_v2_api(); + if (per_monitor_dpi_v2_api) { + return per_monitor_dpi_v2_api->get_dpi_for_system(); + } + + HDC screen_hdc = GetDC(nullptr); + if (!screen_hdc) { + return USER_DEFAULT_SCREEN_DPI; + } + // According to MSDN, x and y are identical. + int logical_pixels_x = GetDeviceCaps(screen_hdc, LOGPIXELSX); + ReleaseDC(nullptr, screen_hdc); + return uint32_t(logical_pixels_x); +} + +uint32_t Win32Window::GetCurrentDpi() const { + if (hwnd_) { + const Win32WindowedAppContext& win32_app_context = + static_cast(app_context()); + + const Win32WindowedAppContext::PerMonitorDpiV2Api* per_monitor_dpi_v2_api = + win32_app_context.per_monitor_dpi_v2_api(); + if (per_monitor_dpi_v2_api) { + return per_monitor_dpi_v2_api->get_dpi_for_window(hwnd_); + } + + const Win32WindowedAppContext::PerMonitorDpiV1Api* per_monitor_dpi_v1_api = + win32_app_context.per_monitor_dpi_v1_api(); + if (per_monitor_dpi_v1_api) { + HMONITOR monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST); + UINT monitor_dpi_x, monitor_dpi_y; + if (monitor && + SUCCEEDED(per_monitor_dpi_v1_api->get_dpi_for_monitor( + monitor, MDT_DEFAULT, &monitor_dpi_x, &monitor_dpi_y))) { + // According to MSDN, x and y are identical. + return monitor_dpi_x; + } + } + } + + return GetCurrentSystemDpi(); +} + +void Win32Window::ApplyFullscreenEntry( + WindowDestructionReceiver& destruction_receiver) { + if (!IsFullscreen()) { + return; + } + + // https://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx + // No reason to use MONITOR_DEFAULTTOPRIMARY instead of + // MONITOR_DEFAULTTONEAREST, however. + pre_fullscreen_dpi_ = dpi_; + pre_fullscreen_placement_.length = sizeof(pre_fullscreen_placement_); + HMONITOR monitor; + MONITORINFO monitor_info; + monitor_info.cbSize = sizeof(monitor_info); + if (!GetWindowPlacement(hwnd_, &pre_fullscreen_placement_) || + !(monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST)) || + !GetMonitorInfo(monitor, &monitor_info)) { + OnDesiredFullscreenUpdate(false); + return; + } + // Preserve values for DPI rescaling of the window in the non-maximized state + // if DPI is changed mid-fullscreen. + // Get the size of the non-client area to subtract it from the size of the + // entire window in its non-maximized state, to get the client area. + RECT non_client_area_rect = {}; + AdjustWindowRectangle(non_client_area_rect); + pre_fullscreen_normal_client_width_ = + uint32_t((pre_fullscreen_placement_.rcNormalPosition.right - + pre_fullscreen_placement_.rcNormalPosition.left) - + (non_client_area_rect.right - non_client_area_rect.left)); + pre_fullscreen_normal_client_height_ = + uint32_t((pre_fullscreen_placement_.rcNormalPosition.bottom - + pre_fullscreen_placement_.rcNormalPosition.top) - + (non_client_area_rect.bottom - non_client_area_rect.top)); + + // Changing the style and the menu may change the size too, don't handle the + // resize multiple times (also potentially with the listeners changing the + // desired fullscreen if called from the handling of some message like + // WM_SIZE). + BeginBatchedSizeUpdate(); + + // Remove the non-client area. + if (GetMainMenu()) { + SetMenu(hwnd_, nullptr); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + } + SetWindowLong(hwnd_, GWL_STYLE, + GetWindowLong(hwnd_, GWL_STYLE) & ~DWORD(WS_OVERLAPPEDWINDOW)); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + + // Resize the window to fullscreen. It is important that this is done _after_ + // disabling the decorations and the menu, to make sure that composition will + // not have to be done for the new size of the window at all, so independent, + // low-latency presentation is possible immediately - if the window was + // involved in composition, it may stay composed persistently until some other + // state change that sometimes helps, sometimes doesn't, even if it becomes + // borderless fullscreen again - this occurs sometimes at least on Windows 11 + // 21H2 on Nvidia GeForce GTX 1070 on driver version 472.12. + SetWindowPos(hwnd_, HWND_TOP, monitor_info.rcMonitor.left, + monitor_info.rcMonitor.top, + monitor_info.rcMonitor.right - monitor_info.rcMonitor.left, + monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top, + SWP_NOOWNERZORDER | SWP_FRAMECHANGED); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + + EndBatchedSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void Win32Window::HandleSizeUpdate( + WindowDestructionReceiver& destruction_receiver) { + if (!hwnd_) { + // Batched size update ended when the window has already been closed, for + // instance. + return; + } + + { + MonitorUpdateEvent e(this, false); + OnMonitorUpdate(e); + } + + // For the desired size in the normal, not maximized and not fullscreen state. + if (!IsFullscreen()) { + WINDOWPLACEMENT window_placement; + window_placement.length = sizeof(window_placement); + if (GetWindowPlacement(hwnd_, &window_placement)) { + // window_placement.rcNormalPosition is the entire window's rectangle, not + // only the client area - convert to client. + // https://devblogs.microsoft.com/oldnewthing/20131017-00/?p=2903 + RECT non_client_rect = {}; + if (AdjustWindowRectangle(non_client_rect)) { + OnDesiredLogicalSizeUpdate( + SizeToLogical(uint32_t((window_placement.rcNormalPosition.right - + non_client_rect.right) - + (window_placement.rcNormalPosition.left - + non_client_rect.left))), + SizeToLogical(uint32_t((window_placement.rcNormalPosition.bottom - + non_client_rect.bottom) - + (window_placement.rcNormalPosition.top - + non_client_rect.top)))); + } + } + } + + // For the actual state. + RECT client_rect; + if (GetClientRect(hwnd_, &client_rect)) { + OnActualSizeUpdate(uint32_t(client_rect.right - client_rect.left), + uint32_t(client_rect.bottom - client_rect.top), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } + } +} + +void Win32Window::BeginBatchedSizeUpdate() { + // It's okay if batched_size_update_contained_* are not false when beginning + // a batched update, in case the new batched update was started by a window + // listener called from within EndBatchedSizeUpdate. + ++batched_size_update_depth_; +} + +void Win32Window::EndBatchedSizeUpdate( + WindowDestructionReceiver& destruction_receiver) { + assert_not_zero(batched_size_update_depth_); + if (--batched_size_update_depth_) { + return; + } + // Resetting batched_size_update_contained_* in closing, not opening, because + // a listener may start a new batch, and finish it, and there won't be need to + // handle the deferred messages twice. + if (batched_size_update_contained_wm_size_) { + batched_size_update_contained_wm_size_ = false; + HandleSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + } + if (batched_size_update_contained_wm_paint_) { + batched_size_update_contained_wm_paint_ = false; + RequestPaint(); + } +} + +bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam, + WindowDestructionReceiver& destruction_receiver) { + // Mouse messages usually contain the position in the client area in lParam, + // but WM_MOUSEWHEEL is an exception, it passes the screen position. + int32_t message_x = GET_X_LPARAM(lParam); + int32_t message_y = GET_Y_LPARAM(lParam); + bool message_pos_is_screen = message == WM_MOUSEWHEEL; + + POINT client_pos = {message_x, message_y}; + if (message_pos_is_screen) { + ScreenToClient(hwnd_, &client_pos); + } + + if (GetCursorVisibility() == CursorVisibility::kAutoHidden) { + POINT screen_pos = {message_x, message_y}; + if (message_pos_is_screen || ClientToScreen(hwnd_, &screen_pos)) { + if (screen_pos.x != cursor_auto_hide_last_screen_pos_.x || + screen_pos.y != cursor_auto_hide_last_screen_pos_.y) { + // WM_MOUSEMOVE messages followed by WM_SETCURSOR may be sent for + // reasons not always involving actual mouse movement performed by the + // user. They're sent when the position of the cursor relative to the + // client area has been changed, as well as other events related to + // window management (including when creating the window), even when not + // interacting with the OS. These should not be revealing the cursor. + // Only revealing it if the mouse has actually been moved. + cursor_currently_auto_hidden_ = false; + SetCursorAutoHideTimer(); + // There's no need to SetCursor here, mouse messages relevant to the + // cursor within the window are always followed by WM_SETCURSOR. + cursor_auto_hide_last_screen_pos_ = screen_pos; + } + } } MouseEvent::Button button = MouseEvent::Button::kNone; - int32_t dx = x - last_mouse_pos_.x; - int32_t dy = y - last_mouse_pos_.y; + int32_t scroll_y = 0; switch (message) { case WM_LBUTTONDOWN: case WM_LBUTTONUP: @@ -673,7 +831,8 @@ bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) { button = MouseEvent::Button::kX2; break; default: - return false; + // Still handle the movement. + break; } break; case WM_MOUSEMOVE: @@ -681,59 +840,412 @@ bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) { break; case WM_MOUSEWHEEL: button = MouseEvent::Button::kNone; - dx = 0; // ? - dy = GET_WHEEL_DELTA_WPARAM(wParam); + static_assert( + MouseEvent::kScrollPerDetent == WHEEL_DELTA, + "Assuming the Windows scroll amount can be passed directly to " + "MouseEvent"); + scroll_y = GET_WHEEL_DELTA_WPARAM(wParam); break; default: - // Double click/etc? - return true; + return false; } - last_mouse_pos_ = {x, y}; - - auto e = MouseEvent(this, button, x, y, dx, dy); + MouseEvent e(this, button, client_pos.x, client_pos.y, 0, scroll_y); switch (message) { case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: - OnMouseDown(&e); + OnMouseDown(e, destruction_receiver); break; case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: - OnMouseUp(&e); + OnMouseUp(e, destruction_receiver); break; case WM_MOUSEMOVE: - OnMouseMove(&e); + OnMouseMove(e, destruction_receiver); break; case WM_MOUSEWHEEL: - OnMouseWheel(&e); + OnMouseWheel(e, destruction_receiver); + break; + default: break; } + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed(). return e.is_handled(); } -bool Win32Window::HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam) { - auto e = KeyEvent( - this, VirtualKey(wParam), lParam & 0xFFFF0000, !!(lParam & 0x2), - !!(GetKeyState(VK_SHIFT) & 0x80), !!(GetKeyState(VK_CONTROL) & 0x80), - !!(GetKeyState(VK_MENU) & 0x80), !!(GetKeyState(VK_LWIN) & 0x80)); +bool Win32Window::HandleKeyboard( + UINT message, WPARAM wParam, LPARAM lParam, + WindowDestructionReceiver& destruction_receiver) { + KeyEvent e(this, VirtualKey(wParam), lParam & 0xFFFF, + !!(lParam & (LPARAM(1) << 30)), !!(GetKeyState(VK_SHIFT) & 0x80), + !!(GetKeyState(VK_CONTROL) & 0x80), + !!(GetKeyState(VK_MENU) & 0x80), !!(GetKeyState(VK_LWIN) & 0x80)); switch (message) { case WM_KEYDOWN: - OnKeyDown(&e); + OnKeyDown(e, destruction_receiver); break; case WM_KEYUP: - OnKeyUp(&e); + OnKeyUp(e, destruction_receiver); break; case WM_CHAR: - OnKeyChar(&e); + OnKeyChar(e, destruction_receiver); + break; + default: break; } + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed(). return e.is_handled(); } +void Win32Window::SetCursorIfFocusedOnClientArea(HCURSOR cursor) const { + if (!HasFocus()) { + return; + } + POINT cursor_pos; + if (!GetCursorPos(&cursor_pos)) { + return; + } + if (WindowFromPoint(cursor_pos) == hwnd_ && + SendMessage(hwnd_, WM_NCHITTEST, 0, + MAKELONG(cursor_pos.x, cursor_pos.y)) == HTCLIENT) { + SetCursor(cursor); + } +} + +void Win32Window::SetCursorAutoHideTimer() { + // Reset the timer by deleting the old timer and creating the new one. + // ChangeTimerQueueTimer doesn't work if the timer has already expired. + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } + // After making sure that the callback is not callable anymore + // (DeleteTimerQueueTimer waits for the completion of the callback if it has + // been called already, or cancels it if it's hasn't), update the most recent + // message revision. + last_cursor_auto_hide_queued = last_cursor_auto_hide_signaled + 1; + CreateTimerQueueTimer(&cursor_auto_hide_timer_, nullptr, + AutoHideCursorTimerCallback, this, + kDefaultCursorAutoHideMilliseconds, 0, + WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE); +} + +void Win32Window::AutoHideCursorTimerCallback(void* parameter, + BOOLEAN timer_or_wait_fired) { + if (!timer_or_wait_fired) { + // Not a timer callback. + return; + } + Win32Window& window = *static_cast(parameter); + window.last_cursor_auto_hide_signaled = window.last_cursor_auto_hide_queued; + SendMessage(window.hwnd_, kUserMessageAutoHideCursor, + window.last_cursor_auto_hide_signaled, 0); +} + +LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, + LPARAM lParam) { + if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) { + WindowDestructionReceiver destruction_receiver(this); + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed() afterwards. + return HandleMouse(message, wParam, lParam, destruction_receiver) + ? 0 + : DefWindowProc(hWnd, message, wParam, lParam); + } + if (message >= WM_KEYFIRST && message <= WM_KEYLAST) { + WindowDestructionReceiver destruction_receiver(this); + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed() afterwards. + return HandleKeyboard(message, wParam, lParam, destruction_receiver) + ? 0 + : DefWindowProc(hWnd, message, wParam, lParam); + } + + switch (message) { + case WM_CLOSE: + // In case the Windows window was somehow forcibly destroyed without + // WM_CLOSE. + case WM_DESTROY: { + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } + { + WindowDestructionReceiver destruction_receiver(this); + OnBeforeClose(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + break; + } + } + // Set hwnd_ to null to ignore events from now on since this Win32Window + // is entering an indeterminate state - this should be done at some point + // in closing anyway. + hwnd_ = nullptr; + SetWindowLongPtr(hWnd, GWLP_USERDATA, 0); + if (message != WM_DESTROY) { + DestroyWindow(hWnd); + } + OnAfterClose(); + } break; + + case WM_DROPFILES: { + HDROP drop_handle = reinterpret_cast(wParam); + auto drop_count = DragQueryFileW(drop_handle, 0xFFFFFFFFu, nullptr, 0); + if (drop_count > 0) { + // Get required buffer size + UINT path_size = DragQueryFileW(drop_handle, 0, nullptr, 0); + if (path_size > 0 && path_size < 0xFFFFFFFFu) { + std::u16string path; + ++path_size; // Ensure space for the null terminator + path.resize(path_size); // Reserve space + // Only getting first file dropped (other files ignored) + path_size = + DragQueryFileW(drop_handle, 0, (LPWSTR)&path[0], path_size); + if (path_size > 0) { + path.resize(path_size); // Will drop the null terminator + FileDropEvent e(this, xe::to_path(path)); + WindowDestructionReceiver destruction_receiver(this); + OnFileDrop(e, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + DragFinish(drop_handle); + break; + } + } + } + } + DragFinish(drop_handle); + } break; + + case WM_MOVE: { + OnMonitorUpdate(MonitorUpdateEvent(this, false)); + } break; + + case WM_SIZE: { + if (batched_size_update_depth_) { + batched_size_update_contained_wm_size_ = true; + } else { + WindowDestructionReceiver destruction_receiver(this); + HandleSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } + } break; + + case WM_PAINT: { + if (batched_size_update_depth_) { + // Avoid painting an outdated surface during a batched size update when + // WM_SIZE handling is deferred. + batched_size_update_contained_wm_paint_ = true; + } else { + ValidateRect(hwnd_, nullptr); + OnPaint(); + } + // Custom painting via OnPaint - don't pass to DefWindowProc. + return 0; + } break; + + case WM_ERASEBKGND: { + if (HasSurface()) { + // Don't erase between paints because painting may be dropped if nothing + // has changed since the last one. + return 0; + } + } break; + + case WM_DISPLAYCHANGE: { + OnMonitorUpdate(MonitorUpdateEvent(this, true)); + } break; + + case WM_DPICHANGED: { + // Note that for some reason, WM_DPICHANGED is not sent when the window is + // borderless fullscreen with per-monitor DPI awareness v1. + + dpi_ = GetCurrentDpi(); + + WindowDestructionReceiver destruction_receiver(this); + + { + UISetupEvent e(this); + OnDpiChanged(e, destruction_receiver); + // The window might have been closed by the handler, check hwnd_ too + // since it's needed below. + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } + + auto rect = reinterpret_cast(lParam); + if (rect) { + // SetWindowPos arguments according to WM_DPICHANGED MSDN documentation. + // https://docs.microsoft.com/en-us/windows/win32/hidpi/wm-dpichanged + // There's no need to handle the maximized state any special way (by + // updating the window placement instead of the window position in this + // case, for instance), as Windows (by design) restores the window when + // changing the DPI to a new one. + SetWindowPos(hwnd_, nullptr, int(rect->left), int(rect->top), + int(rect->right - rect->left), + int(rect->bottom - rect->top), + SWP_NOZORDER | SWP_NOACTIVATE); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } + } break; + + case WM_KILLFOCUS: { + WindowDestructionReceiver destruction_receiver(this); + OnFocusUpdate(false, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + case WM_SETFOCUS: { + WindowDestructionReceiver destruction_receiver(this); + OnFocusUpdate(true, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + case WM_SETCURSOR: { + if (reinterpret_cast(wParam) == hwnd_ && HasFocus() && + LOWORD(lParam) == HTCLIENT) { + switch (GetCursorVisibility()) { + case CursorVisibility::kAutoHidden: { + // Always revealing the cursor in case of events like clicking, but + // WM_MOUSEMOVE messages may be sent for reasons not always + // involving actual mouse movement performed by the user. Revealing + // the cursor in case of movement is done in HandleMouse instead. + if (HIWORD(lParam) != WM_MOUSEMOVE) { + cursor_currently_auto_hidden_ = false; + SetCursorAutoHideTimer(); + } + if (cursor_currently_auto_hidden_) { + SetCursor(nullptr); + return TRUE; + } + } break; + case CursorVisibility::kHidden: + SetCursor(nullptr); + return TRUE; + default: + break; + } + } + // For the non-client area, and for visible cursor, letting normal + // processing happen, setting the cursor to an arrow or to something + // specific to non-client parts of the window. + } break; + + case kUserMessageAutoHideCursor: { + // Recheck the cursor visibility - the callback might have been called + // before or while the timer is deleted. Also ignore messages from + // outdated mouse interactions. + if (GetCursorVisibility() == CursorVisibility::kAutoHidden && + wParam == last_cursor_auto_hide_queued) { + // The timer object is not needed anymore. + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } + cursor_currently_auto_hidden_ = true; + SetCursorIfFocusedOnClientArea(nullptr); + } + return 0; + } break; + + case WM_TABLET_QUERYSYSTEMGESTURESTATUS: + return + // disables press and hold (right-click) gesture + TABLET_DISABLE_PRESSANDHOLD | + // disables UI feedback on pen up (waves) + TABLET_DISABLE_PENTAPFEEDBACK | + // disables UI feedback on pen button down (circle) + TABLET_DISABLE_PENBARRELFEEDBACK | + // disables pen flicks (back, forward, drag down, drag up) + TABLET_DISABLE_FLICKS | TABLET_DISABLE_TOUCHSWITCH | + TABLET_DISABLE_SMOOTHSCROLLING | TABLET_DISABLE_TOUCHUIFORCEON | + TABLET_ENABLE_MULTITOUCHDATA; + + case WM_MENUCOMMAND: { + MENUINFO menu_info = {0}; + menu_info.cbSize = sizeof(menu_info); + menu_info.fMask = MIM_MENUDATA; + GetMenuInfo(HMENU(lParam), &menu_info); + auto parent_item = reinterpret_cast(menu_info.dwMenuData); + auto child_item = + reinterpret_cast(parent_item->child(wParam)); + assert_not_null(child_item); + WindowDestructionReceiver destruction_receiver(this); + child_item->OnSelected(); + if (destruction_receiver.IsWindowDestroyed()) { + break; + } + // The menu item might have been destroyed by its OnSelected, don't do + // anything with it here from now on. + } break; + } + + // The window might have been destroyed by the handlers, don't interact with + // *this in this function from now on. + + // Passing the original hWnd argument rather than hwnd_ as the window might + // have been closed or destroyed by a handler, making hwnd_ null even though + // DefWindowProc still needs to be called to propagate the closing-related + // messages needed by Windows, or inaccessible (due to use-after-free) at all. + return DefWindowProc(hWnd, message, wParam, lParam); +} + +LRESULT CALLBACK Win32Window::WndProcThunk(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) { + if (hWnd) { + Win32Window* window = nullptr; + if (message == WM_NCCREATE) { + auto create_struct = reinterpret_cast(lParam); + window = reinterpret_cast(create_struct->lpCreateParams); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)window); + // Don't miss any messages (as they may have effect on the actual state + // stored in Win32Window) sent before the completion of CreateWindowExW + // dropped because `window->hwnd_ != hWnd`, when the result of + // CreateWindowExW still hasn't been assigned to `hwnd_` (however, don't + // reattach this window to a closed window if WM_NCCREATE was somehow sent + // to a window being closed). + if (window->phase() == Phase::kOpening) { + assert_true(!window->hwnd_ || window->hwnd_ == hWnd); + window->hwnd_ = hWnd; + } + // Enable non-client area DPI scaling for AdjustWindowRectExForDpi to work + // correctly between Windows 10 1607 (when AdjustWindowRectExForDpi and + // EnableNonClientDpiScaling were added) and 1703 (when per-monitor + // awareness version 2 was added with automatically enabled non-client + // area DPI scaling). + const Win32WindowedAppContext& win32_app_context = + static_cast(window->app_context()); + const Win32WindowedAppContext::PerMonitorDpiV2Api* + per_monitor_dpi_v2_api = win32_app_context.per_monitor_dpi_v2_api(); + if (per_monitor_dpi_v2_api) { + per_monitor_dpi_v2_api->enable_non_client_dpi_scaling(hWnd); + } + // Already fully handled, no need to call Win32Window::WndProc. + } else { + window = + reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (window && window->hwnd_ == hWnd) { + return window->WndProc(hWnd, message, wParam, lParam); + } + } + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + std::unique_ptr MenuItem::Create(Type type, const std::string& text, const std::string& hotkey, @@ -772,20 +1284,12 @@ Win32MenuItem::~Win32MenuItem() { } } -void Win32MenuItem::EnableMenuItem(Window& window) { - int i = 0; - for (auto iter = children_.begin(); iter != children_.end(); ++iter, i++) { - ::EnableMenuItem(handle_, i, MF_BYPOSITION | MF_ENABLED); +void Win32MenuItem::SetEnabled(bool enabled) { + UINT enable_flags = MF_BYPOSITION | (enabled ? MF_ENABLED : MF_GRAYED); + UINT i = 0; + for (auto iter = children_.begin(); iter != children_.end(); ++iter, ++i) { + EnableMenuItem(handle_, i, enable_flags); } - DrawMenuBar((HWND)window.native_handle()); -} - -void Win32MenuItem::DisableMenuItem(Window& window) { - int i = 0; - for (auto iter = children_.begin(); iter != children_.end(); ++iter, i++) { - ::EnableMenuItem(handle_, i, MF_BYPOSITION | MF_GRAYED); - } - DrawMenuBar((HWND)window.native_handle()); } void Win32MenuItem::OnChildAdded(MenuItem* generic_child_item) { diff --git a/src/xenia/ui/window_win.h b/src/xenia/ui/window_win.h index f4dceaeac..dd5d8b978 100644 --- a/src/xenia/ui/window_win.h +++ b/src/xenia/ui/window_win.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,10 +13,15 @@ #include #include -#include "xenia/base/platform_win.h" #include "xenia/ui/menu_item.h" #include "xenia/ui/window.h" +// Must be included before Windows headers for things like NOMINMAX. +#include "xenia/base/platform_win.h" + +#include +#include + namespace xe { namespace ui { @@ -24,73 +29,127 @@ class Win32Window : public Window { using super = Window; public: - Win32Window(WindowedAppContext& app_context, const std::string& title); + Win32Window(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height); ~Win32Window() override; - NativePlatformHandle native_platform_handle() const override; - NativeWindowHandle native_handle() const override { return hwnd_; } + // Will be null if the window hasn't been successfully opened yet, or has been + // closed. HWND hwnd() const { return hwnd_; } - void EnableMainMenu() override; - void DisableMainMenu() override; - - bool set_title(const std::string_view title) override; - - bool SetIcon(const void* buffer, size_t size) override; - - bool CaptureMouse() override; - bool ReleaseMouse() override; - - bool is_fullscreen() const override; - void ToggleFullscreen(bool fullscreen) override; - - bool is_bordered() const override; - void set_bordered(bool enabled) override; - - int get_dpi() const override; - - void set_cursor_visible(bool value) override; - void set_focus(bool value) override; - - void Resize(int32_t width, int32_t height) override; - void Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) override; - - // (raw) Resize the window, no DPI scaling applied. - void RawReposition(const RECT& rc); - - bool Initialize() override; - void Invalidate() override; - void Close() override; + uint32_t GetMediumDpi() const override; protected: - bool OnCreate() override; - void OnMainMenuChange() override; - void OnDestroy() override; - void OnClose() override; + bool OpenImpl() override; + void RequestCloseImpl() override; - void OnResize(UIEvent* e) override; + uint32_t GetLatestDpiImpl() const override; + + void ApplyNewFullscreen() override; + void ApplyNewTitle() override; + void LoadAndApplyIcon(const void* buffer, size_t size, + bool can_apply_state_in_current_phase) override; + void ApplyNewMainMenu(MenuItem* old_main_menu) override; + void CompleteMainMenuItemsUpdateImpl() override; + void ApplyNewMouseCapture() override; + void ApplyNewMouseRelease() override; + void ApplyNewCursorVisibility( + CursorVisibility old_cursor_visibility) override; + void FocusImpl() override; + + std::unique_ptr CreateSurfaceImpl( + Surface::TypeFlags allowed_types) override; + void RequestPaintImpl() override; + + private: + enum : UINT { + kUserMessageAutoHideCursor = WM_USER, + }; + + BOOL AdjustWindowRectangle(RECT& rect, DWORD style, BOOL menu, DWORD ex_style, + UINT dpi) const; + BOOL AdjustWindowRectangle(RECT& rect) const; + + uint32_t GetCurrentSystemDpi() const; + uint32_t GetCurrentDpi() const; + + void ApplyFullscreenEntry(WindowDestructionReceiver& destruction_receiver); + + void HandleSizeUpdate(WindowDestructionReceiver& destruction_receiver); + // For updating multiple factors that may influence the window size at once, + // without handling WM_SIZE multiple times (that may not only result in wasted + // handling, but also in the state potentially changed to an inconsistent one + // in the middle of a size update by the listeners). + void BeginBatchedSizeUpdate(); + void EndBatchedSizeUpdate(WindowDestructionReceiver& destruction_receiver); + + bool HandleMouse(UINT message, WPARAM wParam, LPARAM lParam, + WindowDestructionReceiver& destruction_receiver); + bool HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam, + WindowDestructionReceiver& destruction_receiver); + + void SetCursorIfFocusedOnClientArea(HCURSOR cursor) const; + void SetCursorAutoHideTimer(); + static void NTAPI AutoHideCursorTimerCallback(void* parameter, + BOOLEAN timer_or_wait_fired); static LRESULT CALLBACK WndProcThunk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + // This can't handle messages sent during CreateWindow (hwnd_ still not + // assigned to) or after nulling hwnd_ in closing / deleting. virtual LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - private: - void EnableMMCSS(); - bool HandleMouse(UINT message, WPARAM wParam, LPARAM lParam); - bool HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam); - - HWND hwnd_ = nullptr; - HICON icon_ = nullptr; - bool closing_ = false; - bool fullscreen_ = false; HCURSOR arrow_cursor_ = nullptr; - WINDOWPLACEMENT windowed_pos_ = {0}; - POINT last_mouse_pos_ = {0}; + HICON icon_ = nullptr; - void* GetDpiForMonitor_ = nullptr; + uint32_t dpi_ = USER_DEFAULT_SCREEN_DPI; + + // hwnd_ may be accessed by the cursor hiding timer callback from a separate + // thread, but the timer can be active only with a valid window anyway. + HWND hwnd_ = nullptr; + + uint32_t batched_size_update_depth_ = 0; + bool batched_size_update_contained_wm_size_ = false; + bool batched_size_update_contained_wm_paint_ = false; + + uint32_t pre_fullscreen_dpi_; + WINDOWPLACEMENT pre_fullscreen_placement_; + // The client area part of pre_fullscreen_placement_.rcNormalPosition, saved + // in case something effecting the behavior of AdjustWindowRectEx for the + // non-fullscreen state is changed mid-fullscreen (for instance, the menu is + // toggled), so a new AdjustWindowRectExForDpi call for the old DPI, but with + // the other state different than the old one, while exiting fullscreen, won't + // cause anomalies like negative size. + uint32_t pre_fullscreen_normal_client_width_; + uint32_t pre_fullscreen_normal_client_height_; + + // Must be the screen position, not the client position, so it's possible to + // immediately hide the cursor, for instance, when switching to fullscreen + // (and thus changing the client area top-left corner, resulting in + // WM_MOUSEMOVE being sent, which would instantly reveal the cursor because of + // that relative position change). + POINT cursor_auto_hide_last_screen_pos_ = {LONG_MAX, LONG_MAX}; + // Using a timer queue timer for hiding the cursor rather than WM_TIMER + // because the latter is a very low-priority message which is never received + // if WM_PAINT messages are sent continuously (invalidating the window right + // after painting). + HANDLE cursor_auto_hide_timer_ = nullptr; + // Last hiding case numbers for skipping of obsolete cursor hiding messages + // (both WM_MOUSEMOVE and the hiding message have been sent, for instance, and + // WM_MOUSEMOVE hasn't been handled yet, or the cursor visibility state has + // been changed). The queued index is read, and the signaled index is written, + // by the timer callback, which is executed outside the message thread, so + // before modifying the queued number, or reading the signaled number, in the + // message thread, delete the timer (deleting the timer awaits cancels the + // callback if it hasn't been invoked yet, or awaits it if it has). Use + // equality comparison for safe rollover handling. + WPARAM last_cursor_auto_hide_queued = 0; + WPARAM last_cursor_auto_hide_signaled = 0; + // Whether the cursor has been hidden after the expiration of the timer, and + // hasn't been revealed yet. + bool cursor_currently_auto_hidden_ = false; }; class Win32MenuItem : public MenuItem { @@ -99,10 +158,9 @@ class Win32MenuItem : public MenuItem { std::function callback); ~Win32MenuItem() override; - HMENU handle() { return handle_; } + HMENU handle() const { return handle_; } - void EnableMenuItem(Window& window) override; - void DisableMenuItem(Window& window) override; + void SetEnabled(bool enabled) override; using MenuItem::OnSelected; diff --git a/src/xenia/ui/windowed_app_context_android.cc b/src/xenia/ui/windowed_app_context_android.cc index 5af4efad6..2deb4e95e 100644 --- a/src/xenia/ui/windowed_app_context_android.cc +++ b/src/xenia/ui/windowed_app_context_android.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -22,6 +24,7 @@ #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/main_android.h" +#include "xenia/ui/window_android.h" #include "xenia/ui/windowed_app.h" namespace xe { @@ -52,6 +55,16 @@ void AndroidWindowedAppContext::PlatformQuitFromUIThread() { } } +void AndroidWindowedAppContext::PostInvalidateWindowSurface() { + // May be called from non-UI threads. + JNIEnv* jni_env = GetAndroidThreadJniEnv(); + if (!jni_env) { + return; + } + jni_env->CallVoidMethod(activity_, + activity_method_post_invalidate_window_surface_); +} + AndroidWindowedAppContext* AndroidWindowedAppContext::JniActivityInitializeWindowedAppOnCreate( JNIEnv* jni_env, jobject activity, jstring windowed_app_identifier, @@ -100,9 +113,54 @@ void AndroidWindowedAppContext::JniActivityOnDestroy() { app_->InvokeOnDestroy(); app_.reset(); } + // Expecting that the destruction of the app will destroy the window as well, + // no need to notify it explicitly. + assert_null(activity_window_); RequestDestruction(); } +void AndroidWindowedAppContext::JniActivityOnWindowSurfaceLayoutChange( + jint left, jint top, jint right, jint bottom) { + window_surface_layout_left_ = left; + window_surface_layout_top_ = top; + window_surface_layout_right_ = right; + window_surface_layout_bottom_ = bottom; + if (activity_window_) { + activity_window_->OnActivitySurfaceLayoutChange(); + } +} + +void AndroidWindowedAppContext::JniActivityOnWindowSurfaceChanged( + jobject window_surface_object) { + // Detach from the old surface. + if (window_surface_) { + ANativeWindow* old_window_surface = window_surface_; + window_surface_ = nullptr; + if (activity_window_) { + activity_window_->OnActivitySurfaceChanged(); + } + ANativeWindow_release(old_window_surface); + } + if (!window_surface_object) { + return; + } + window_surface_ = + ANativeWindow_fromSurface(ui_thread_jni_env_, window_surface_object); + if (!window_surface_) { + return; + } + if (activity_window_) { + activity_window_->OnActivitySurfaceChanged(); + } +} + +void AndroidWindowedAppContext::JniActivityPaintWindow(bool force_paint) { + if (!activity_window_) { + return; + } + activity_window_->PaintActivitySurface(force_paint); +} + AndroidWindowedAppContext::~AndroidWindowedAppContext() { Shutdown(); } bool AndroidWindowedAppContext::Initialize(JNIEnv* ui_thread_jni_env, @@ -141,11 +199,56 @@ bool AndroidWindowedAppContext::Initialize(JNIEnv* ui_thread_jni_env, } AConfiguration_fromAssetManager(configuration_, asset_manager_); - // Initialize Xenia globals that may depend on the API level, as well as - // logging. + // Get the activity class, needed for the application context here, and for + // other activity interaction later. + { + jclass activity_class_local_ref = + ui_thread_jni_env_->GetObjectClass(activity); + if (!activity_class_local_ref) { + __android_log_write(ANDROID_LOG_ERROR, "AndroidWindowedAppContext", + "Failed to get the activity class"); + Shutdown(); + return false; + } + activity_class_ = reinterpret_cast(ui_thread_jni_env_->NewGlobalRef( + reinterpret_cast(activity_class_local_ref))); + ui_thread_jni_env_->DeleteLocalRef( + reinterpret_cast(activity_class_local_ref)); + } + if (!activity_class_) { + __android_log_write( + ANDROID_LOG_ERROR, "AndroidWindowedAppContext", + "Failed to create a global reference to the activity class"); + Shutdown(); + return false; + } + + // Get the application context. + jmethodID activity_get_application_context = ui_thread_jni_env_->GetMethodID( + activity_class_, "getApplicationContext", "()Landroid/content/Context;"); + if (!activity_get_application_context) { + __android_log_write( + ANDROID_LOG_ERROR, "AndroidWindowedAppContext", + "Failed to get the getApplicationContext method of the activity"); + Shutdown(); + return false; + } + jobject application_context_init_ref = ui_thread_jni_env_->CallObjectMethod( + activity, activity_get_application_context); + if (!application_context_init_ref) { + __android_log_write( + ANDROID_LOG_ERROR, "AndroidWindowedAppContext", + "Failed to get the application context from the activity"); + Shutdown(); + return false; + } + + // Initialize Xenia globals that may depend on the base globals and logging. xe::InitializeAndroidAppFromMainThread( - AConfiguration_getSdkVersion(configuration_)); + AConfiguration_getSdkVersion(configuration_), ui_thread_jni_env_, + application_context_init_ref); android_base_initialized_ = true; + ui_thread_jni_env_->DeleteLocalRef(application_context_init_ref); // Initialize interfacing with the WindowedAppActivity. activity_ = ui_thread_jni_env_->NewGlobalRef(activity); @@ -156,30 +259,15 @@ bool AndroidWindowedAppContext::Initialize(JNIEnv* ui_thread_jni_env, Shutdown(); return false; } - { - jclass activity_class_local_ref = - ui_thread_jni_env_->GetObjectClass(activity); - if (!activity_class_local_ref) { - XELOGE("AndroidWindowedAppContext: Failed to get the activity class"); - Shutdown(); - return false; - } - activity_class_ = reinterpret_cast(ui_thread_jni_env_->NewGlobalRef( - reinterpret_cast(activity_class_local_ref))); - ui_thread_jni_env_->DeleteLocalRef( - reinterpret_cast(activity_class_local_ref)); - } - if (!activity_class_) { - XELOGE( - "AndroidWindowedAppContext: Failed to create a global reference to the " - "activity class"); - Shutdown(); - return false; - } bool activity_ids_obtained = true; activity_ids_obtained &= (activity_method_finish_ = ui_thread_jni_env_->GetMethodID( activity_class_, "finish", "()V")) != nullptr; + activity_ids_obtained &= + (activity_method_post_invalidate_window_surface_ = + ui_thread_jni_env_->GetMethodID( + activity_class_, "postInvalidateWindowSurface", "()V")) != + nullptr; if (!activity_ids_obtained) { XELOGE("AndroidWindowedAppContext: Failed to get the activity class IDs"); Shutdown(); @@ -249,11 +337,6 @@ void AndroidWindowedAppContext::Shutdown() { } activity_method_finish_ = nullptr; - if (activity_class_) { - ui_thread_jni_env_->DeleteGlobalRef( - reinterpret_cast(activity_class_)); - activity_class_ = nullptr; - } if (activity_) { ui_thread_jni_env_->DeleteGlobalRef(activity_); activity_ = nullptr; @@ -264,6 +347,12 @@ void AndroidWindowedAppContext::Shutdown() { android_base_initialized_ = false; } + if (activity_class_) { + ui_thread_jni_env_->DeleteGlobalRef( + reinterpret_cast(activity_class_)); + activity_class_ = nullptr; + } + if (configuration_) { AConfiguration_delete(configuration_); configuration_ = nullptr; @@ -381,7 +470,7 @@ bool AndroidWindowedAppContext::InitializeApp(std::unique_ptr ( extern "C" { JNIEXPORT jlong JNICALL -Java_jp_xenia_emulator_WindowedAppActivity_initializeWindowedAppOnCreateNative( +Java_jp_xenia_emulator_WindowedAppActivity_initializeWindowedAppOnCreate( JNIEnv* jni_env, jobject activity, jstring windowed_app_identifier, jobject asset_manager) { return reinterpret_cast( @@ -397,4 +486,27 @@ Java_jp_xenia_emulator_WindowedAppActivity_onDestroyNative( ->JniActivityOnDestroy(); } +JNIEXPORT void JNICALL +Java_jp_xenia_emulator_WindowedAppActivity_onWindowSurfaceLayoutChange( + JNIEnv* jni_env, jobject activity, jlong app_context_ptr, jint left, + jint top, jint right, jint bottom) { + reinterpret_cast(app_context_ptr) + ->JniActivityOnWindowSurfaceLayoutChange(left, top, right, bottom); +} + +JNIEXPORT void JNICALL +Java_jp_xenia_emulator_WindowedAppActivity_onWindowSurfaceChanged( + JNIEnv* jni_env, jobject activity, jlong app_context_ptr, + jobject window_surface_object) { + reinterpret_cast(app_context_ptr) + ->JniActivityOnWindowSurfaceChanged(window_surface_object); +} + +JNIEXPORT void JNICALL Java_jp_xenia_emulator_WindowedAppActivity_paintWindow( + JNIEnv* jni_env, jobject activity, jlong app_context_ptr, + jboolean force_paint) { + reinterpret_cast(app_context_ptr) + ->JniActivityPaintWindow(bool(force_paint)); +} + } // extern "C" diff --git a/src/xenia/ui/windowed_app_context_android.h b/src/xenia/ui/windowed_app_context_android.h index 91cd10427..022826fc1 100644 --- a/src/xenia/ui/windowed_app_context_android.h +++ b/src/xenia/ui/windowed_app_context_android.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -33,10 +34,32 @@ class AndroidWindowedAppContext final : public WindowedAppContext { void PlatformQuitFromUIThread() override; + uint32_t GetPixelDensity() const { + return configuration_ ? uint32_t(AConfiguration_getDensity(configuration_)) + : 160; + } + + int32_t window_surface_layout_left() const { + return window_surface_layout_left_; + } + int32_t window_surface_layout_top() const { + return window_surface_layout_top_; + } + int32_t window_surface_layout_right() const { + return window_surface_layout_right_; + } + int32_t window_surface_layout_bottom() const { + return window_surface_layout_bottom_; + } + + ANativeWindow* GetWindowSurface() const { return window_surface_; } + void PostInvalidateWindowSurface(); + // The single Window instance that will be receiving window callbacks. // Multiple windows cannot be created as one activity or fragment can have // only one layout. This window acts purely as a proxy between the activity - // and the Xenia logic. + // and the Xenia logic. May be done during Window destruction, so must not + // interact with it. AndroidWindow* GetActivityWindow() const { return activity_window_; } void SetActivityWindow(AndroidWindow* window) { activity_window_ = window; } @@ -45,6 +68,10 @@ class AndroidWindowedAppContext final : public WindowedAppContext { JNIEnv* jni_env, jobject activity, jstring windowed_app_identifier, jobject asset_manager); void JniActivityOnDestroy(); + void JniActivityOnWindowSurfaceLayoutChange(jint left, jint top, jint right, + jint bottom); + void JniActivityOnWindowSurfaceChanged(jobject window_surface_object); + void JniActivityPaintWindow(bool force_paint); private: enum class UIThreadLooperCallbackCommand : uint8_t { @@ -77,14 +104,6 @@ class AndroidWindowedAppContext final : public WindowedAppContext { bool InitializeApp(std::unique_ptr (*app_creator)( WindowedAppContext& app_context)); - // Useful notes about JNI usage on Android within Xenia: - // - All static libraries defining JNI native functions must be linked to - // shared libraries via LOCAL_WHOLE_STATIC_LIBRARIES. - // - If method or field IDs are cached, a global reference to the class needs - // to be held - it prevents the class from being unloaded by the class - // loaders (in a way that would make the IDs invalid when it's reloaded). - // - GetStringUTFChars (UTF-8) returns null-terminated strings, GetStringChars - // (UTF-16) does not. JNIEnv* ui_thread_jni_env_ = nullptr; // The object reference must be held by the app according to @@ -94,11 +113,13 @@ class AndroidWindowedAppContext final : public WindowedAppContext { AConfiguration* configuration_ = nullptr; + jclass activity_class_ = nullptr; + bool android_base_initialized_ = false; jobject activity_ = nullptr; - jclass activity_class_ = nullptr; jmethodID activity_method_finish_ = nullptr; + jmethodID activity_method_post_invalidate_window_surface_ = nullptr; // May be read by non-UI threads in NotifyUILoopOfPendingFunctions. ALooper* ui_thread_looper_ = nullptr; @@ -107,6 +128,13 @@ class AndroidWindowedAppContext final : public WindowedAppContext { std::array ui_thread_looper_callback_pipe_{-1, -1}; bool ui_thread_looper_callback_registered_ = false; + int32_t window_surface_layout_left_ = 0; + int32_t window_surface_layout_top_ = 0; + int32_t window_surface_layout_right_ = 0; + int32_t window_surface_layout_bottom_ = 0; + + ANativeWindow* window_surface_ = nullptr; + AndroidWindow* activity_window_ = nullptr; std::unique_ptr app_; diff --git a/src/xenia/ui/windowed_app_context_win.cc b/src/xenia/ui/windowed_app_context_win.cc index 399a2afd4..f9371304a 100644 --- a/src/xenia/ui/windowed_app_context_win.cc +++ b/src/xenia/ui/windowed_app_context_win.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -22,10 +22,43 @@ Win32WindowedAppContext::~Win32WindowedAppContext() { if (pending_functions_hwnd_) { DestroyWindow(pending_functions_hwnd_); } + if (shcore_module_) { + FreeLibrary(shcore_module_); + } } bool Win32WindowedAppContext::Initialize() { // Logging possibly not initialized in this function yet. + + // Obtain function pointers that may be used for windows if available. + shcore_module_ = LoadLibraryW(L"SHCore.dll"); + if (shcore_module_) { + per_monitor_dpi_v1_api_available_ = true; + per_monitor_dpi_v1_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v1_api_.get_dpi_for_monitor) = + GetProcAddress(shcore_module_, "GetDpiForMonitor")) != nullptr; + per_monitor_dpi_v2_api_available_ = true; + per_monitor_dpi_v2_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v2_api_.adjust_window_rect_ex_for_dpi) = + GetProcAddress(shcore_module_, "AdjustWindowRectExForDpi")) != + nullptr; + per_monitor_dpi_v2_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v2_api_.enable_non_client_dpi_scaling) = + GetProcAddress(shcore_module_, "EnableNonClientDpiScaling")) != + nullptr; + per_monitor_dpi_v2_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v2_api_.get_dpi_for_system) = + GetProcAddress(shcore_module_, "GetDpiForSystem")) != nullptr; + per_monitor_dpi_v2_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v2_api_.get_dpi_for_window) = + GetProcAddress(shcore_module_, "GetDpiForWindow")) != nullptr; + } + // Create the message-only window for executing pending functions - using a // window instead of executing them between iterations so non-main message // loops, such as Windows modals, can execute pending functions too. @@ -51,6 +84,7 @@ bool Win32WindowedAppContext::Initialize() { if (!pending_functions_hwnd_) { return false; } + return true; } @@ -117,7 +151,7 @@ LRESULT CALLBACK Win32WindowedAppContext::PendingFunctionsWndProc( break; case kPendingFunctionsWindowClassMessageExecute: app_context->ExecutePendingFunctionsFromUIThread(); - break; + return 0; default: break; } diff --git a/src/xenia/ui/windowed_app_context_win.h b/src/xenia/ui/windowed_app_context_win.h index 1c01961ac..08e70e662 100644 --- a/src/xenia/ui/windowed_app_context_win.h +++ b/src/xenia/ui/windowed_app_context_win.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -15,11 +15,42 @@ #include "xenia/base/platform_win.h" #include "xenia/ui/windowed_app_context.h" +// For per-monitor DPI awareness v1. +#include + namespace xe { namespace ui { class Win32WindowedAppContext final : public WindowedAppContext { public: + // clang-format off + struct PerMonitorDpiV1Api { + HRESULT (STDAPICALLTYPE* get_dpi_for_monitor)( + HMONITOR hmonitor, MONITOR_DPI_TYPE dpi_type, UINT* dpi_x, UINT* dpi_y); + }; + struct PerMonitorDpiV2Api { + // Important note: Even though per-monitor DPI awareness version 2 + // inherently has automatic non-client area DPI scaling, PMv2 was added in + // Windows 10 1703. However, these functions were added earlier, in 1607. + // While we haven't tested the actual behavior on 1607 and this is just a + // guess, still, before using AdjustWindowRectExForDpi for the window DPI, + // make sure that EnableNonClientDpiScaling is called for the window in its + // WM_NCCREATE handler to enable automatic non-client DPI scaling on PMv1 on + // 1607, so AdjustWindowRectExForDpi (which doesn't have a window argument + // so it can't know whether automatic scaling is enabled for it) will likely + // return values that reflect the actual size of the non-client area of the + // window (otherwise, for instance, "un-adjusting" the actual window + // rectangle using AdjustWindowRectExForDpi may result in a negative client + // area size if the DPI passed to it is larger than the DPI actually used + // for the non-client area). + BOOL (WINAPI* adjust_window_rect_ex_for_dpi)( + LPRECT rect, DWORD style, BOOL menu, DWORD ex_style, UINT dpi); + BOOL (WINAPI* enable_non_client_dpi_scaling)(HWND hwnd); + UINT (WINAPI* get_dpi_for_system)(); + UINT (WINAPI* get_dpi_for_window)(HWND hwnd); + }; + // clang-format on + // Must call Initialize and check its result after creating to be able to // perform pending function calls. explicit Win32WindowedAppContext(HINSTANCE hinstance, int show_cmd) @@ -37,6 +68,23 @@ class Win32WindowedAppContext final : public WindowedAppContext { int RunMainMessageLoop(); + // Per-monitor DPI awareness version 2 is expected to be enabled via the + // manifest, as that's the recommended way, which also doesn't require calling + // SetProcessDpiAwareness before doing anything that may depend on DPI + // awareness (so it's safe to use any Windows APIs before what would be + // supposed to initialize it). + // Windows 8.1 per-monitor DPI awareness version 1. + const PerMonitorDpiV1Api* per_monitor_dpi_v1_api() const { + return per_monitor_dpi_v1_api_available_ ? &per_monitor_dpi_v1_api_ + : nullptr; + } + // Windows 10 1607 per-monitor DPI awareness API, also heavily used for + // per-monitor DPI awareness version 2 functionality added in Windows 10 1703. + const PerMonitorDpiV2Api* per_monitor_dpi_v2_api() const { + return per_monitor_dpi_v2_api_available_ ? &per_monitor_dpi_v2_api_ + : nullptr; + } + private: enum : UINT { kPendingFunctionsWindowClassMessageExecute = WM_USER, @@ -47,9 +95,15 @@ class Win32WindowedAppContext final : public WindowedAppContext { HINSTANCE hinstance_; int show_cmd_; - HWND pending_functions_hwnd_ = nullptr; + + HMODULE shcore_module_ = nullptr; + PerMonitorDpiV1Api per_monitor_dpi_v1_api_ = {}; + PerMonitorDpiV2Api per_monitor_dpi_v2_api_ = {}; + bool per_monitor_dpi_v1_api_available_ = false; + bool per_monitor_dpi_v2_api_available_ = false; static bool pending_functions_window_class_registered_; + HWND pending_functions_hwnd_ = nullptr; }; } // namespace ui diff --git a/src/xenia/ui/windowed_app_main_posix.cc b/src/xenia/ui/windowed_app_main_posix.cc index 60b93a04e..dc99e243d 100644 --- a/src/xenia/ui/windowed_app_main_posix.cc +++ b/src/xenia/ui/windowed_app_main_posix.cc @@ -18,6 +18,10 @@ #include "xenia/ui/windowed_app_context_gtk.h" extern "C" int main(int argc_pre_gtk, char** argv_pre_gtk) { + // Before touching anything GTK+, make sure that when running on Wayland, + // we'll still get an X11 (Xwayland) window + setenv("GDK_BACKEND", "x11", 1); + // Initialize GTK+, which will handle and remove its own arguments from argv. // Both GTK+ and Xenia use --option=value argument format (see man // gtk-options), however, it's meaningless to try to parse the same argument diff --git a/src/xenia/vfs/devices/disc_image_device.cc b/src/xenia/vfs/devices/disc_image_device.cc index d5ae0c15f..561d0cef7 100644 --- a/src/xenia/vfs/devices/disc_image_device.cc +++ b/src/xenia/vfs/devices/disc_image_device.cc @@ -9,6 +9,7 @@ #include "xenia/vfs/devices/disc_image_device.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/vfs/devices/disc_image_entry.h" @@ -16,7 +17,9 @@ namespace xe { namespace vfs { -const size_t kXESectorSize = 2048; +using namespace xe::literals; + +const size_t kXESectorSize = 2_KiB; DiscImageDevice::DiscImageDevice(const std::string_view mount_path, const std::filesystem::path& host_path) @@ -89,7 +92,7 @@ DiscImageDevice::Error DiscImageDevice::Verify(ParseState* state) { state->root_size = xe::load(fs_ptr + 24); state->root_offset = state->game_offset + (state->root_sector * kXESectorSize); - if (state->root_size < 13 || state->root_size > 32 * 1024 * 1024) { + if (state->root_size < 13 || state->root_size > 32_MiB) { return Error::kErrorDamagedFile; } diff --git a/src/xenia/vfs/vfs_dump.cc b/src/xenia/vfs/vfs_dump.cc index 2bca814bb..f2416b59a 100644 --- a/src/xenia/vfs/vfs_dump.cc +++ b/src/xenia/vfs/vfs_dump.cc @@ -13,6 +13,7 @@ #include "xenia/base/console_app_main.h" #include "xenia/base/cvar.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" @@ -22,6 +23,8 @@ namespace xe { namespace vfs { +using namespace xe::literals; + DEFINE_transient_path(source, "", "Specifies the file to dump from.", "General"); @@ -91,7 +94,7 @@ int vfs_dump_main(const std::vector& args) { } // Allocate a buffer rounded up to the nearest 512MB. - buffer_size = xe::round_up(entry->size(), 512 * 1024 * 1024); + buffer_size = xe::round_up(entry->size(), 512_MiB); buffer = new uint8_t[buffer_size]; } diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index d27d37661..574501788 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -312,7 +312,8 @@ struct X_OBJECT_ATTRIBUTES { // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082.aspx typedef struct { - xe::be exception_code; + // Renamed due to a collision with exception_code from Windows excpt.h. + xe::be code; xe::be exception_flags; xe::be exception_record; xe::be exception_address; diff --git a/third_party/.clang-format b/third_party/.clang-format new file mode 100644 index 000000000..9d159247d --- /dev/null +++ b/third_party/.clang-format @@ -0,0 +1,2 @@ +DisableFormat: true +SortIncludes: false diff --git a/third_party/FidelityFX-CAS b/third_party/FidelityFX-CAS new file mode 160000 index 000000000..9fabcc9a2 --- /dev/null +++ b/third_party/FidelityFX-CAS @@ -0,0 +1 @@ +Subproject commit 9fabcc9a2c45f958aff55ddfda337e74ef894b7f diff --git a/third_party/FidelityFX-FSR b/third_party/FidelityFX-FSR new file mode 160000 index 000000000..a21ffb8f6 --- /dev/null +++ b/third_party/FidelityFX-FSR @@ -0,0 +1 @@ +Subproject commit a21ffb8f6c13233ba336352bdff293894c706575 diff --git a/third_party/SDL2 b/third_party/SDL2 index ea9bece5e..b424665e0 160000 --- a/third_party/SDL2 +++ b/third_party/SDL2 @@ -1 +1 @@ -Subproject commit ea9bece5ed4e76b6636d941101923487a6378ca6 +Subproject commit b424665e0899769b200231ba943353a5fee1b6b6 diff --git a/third_party/SDL2-static.lua b/third_party/SDL2-static.lua index 492c0d3d9..d03a607a5 100644 --- a/third_party/SDL2-static.lua +++ b/third_party/SDL2-static.lua @@ -42,6 +42,7 @@ project("SDL2") "SDL2/include/SDL_gesture.h", "SDL2/include/SDL_haptic.h", "SDL2/include/SDL_hints.h", + "SDL2/include/SDL_hidapi.h", "SDL2/include/SDL_joystick.h", "SDL2/include/SDL_keyboard.h", "SDL2/include/SDL_keycode.h", @@ -133,7 +134,7 @@ project("SDL2") "SDL2/src/haptic/windows/SDL_windowshaptic_c.h", "SDL2/src/haptic/windows/SDL_xinputhaptic_c.h", "SDL2/src/hidapi/hidapi/hidapi.h", - "SDL2/src/hidapi/SDL_hidapi.h", + "SDL2/src/hidapi/SDL_hidapi_c.h", "SDL2/src/joystick/controller_type.h", "SDL2/src/joystick/hidapi/SDL_hidapijoystick_c.h", "SDL2/src/joystick/hidapi/SDL_hidapi_rumble.h", @@ -168,6 +169,7 @@ project("SDL2") "SDL2/src/render/software/SDL_drawpoint.h", "SDL2/src/render/software/SDL_render_sw_c.h", "SDL2/src/render/software/SDL_rotate.h", + "SDL2/src/render/software/SDL_triangle.h", "SDL2/src/SDL_assert_c.h", "SDL2/src/SDL_dataqueue.h", "SDL2/src/SDL_error_c.h", @@ -293,7 +295,6 @@ project("SDL2") "SDL2/src/joystick/SDL_joystick.c", "SDL2/src/joystick/virtual/SDL_virtualjoystick.c", "SDL2/src/joystick/windows/SDL_dinputjoystick.c", - "SDL2/src/joystick/windows/SDL_mmjoystick.c", "SDL2/src/joystick/windows/SDL_rawinputjoystick.c", "SDL2/src/joystick/windows/SDL_windowsjoystick.c", "SDL2/src/joystick/windows/SDL_windows_gaming_input.c", @@ -343,6 +344,7 @@ project("SDL2") "SDL2/src/render/software/SDL_drawpoint.c", "SDL2/src/render/software/SDL_render_sw.c", "SDL2/src/render/software/SDL_rotate.c", + "SDL2/src/render/software/SDL_triangle.c", "SDL2/src/SDL.c", "SDL2/src/SDL_assert.c", "SDL2/src/SDL_dataqueue.c", @@ -362,7 +364,7 @@ project("SDL2") "SDL2/src/stdlib/SDL_strtokr.c", "SDL2/src/thread/generic/SDL_syscond.c", "SDL2/src/thread/SDL_thread.c", - "SDL2/src/thread/windows/SDL_syscond_srw.c", + "SDL2/src/thread/windows/SDL_syscond_cv.c", "SDL2/src/thread/windows/SDL_sysmutex.c", "SDL2/src/thread/windows/SDL_syssem.c", "SDL2/src/thread/windows/SDL_systhread.c", diff --git a/third_party/fxaa/FXAA3_11.h b/third_party/fxaa/FXAA3_11.h new file mode 100644 index 000000000..993966d10 --- /dev/null +++ b/third_party/fxaa/FXAA3_11.h @@ -0,0 +1,2065 @@ +//---------------------------------------------------------------------------------- +// File: es3-kepler\FXAA/FXAA3_11.h +// SDK Version: v2.11 +// Email: gameworks@nvidia.com +// Site: http://developer.nvidia.com/ +// +// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//---------------------------------------------------------------------------------- +/*============================================================================ + + + NVIDIA FXAA 3.11 by TIMOTHY LOTTES + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_5 1 + #define FXAA_QUALITY__PRESET 12 + +Or, + + #define FXAA_360 1 + +Or, + + #define FXAA_PS3 1 + +Etc. + +(2.) +Then include this file, + + #include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + + return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + + #define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + + // {xy} = center of pixel + FxaaFloat2 pos, + + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + + #define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS + // + // Consoles the sharpness of edges on PS3 only. + // Non-PS3 tuning is done with shader input. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD + // + // Only effects PS3. + // Non-PS3 tuning is done with shader input. + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 + #endif +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY__PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY__PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 3.0 + #define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 3.0 + #define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 4.0 + #define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 4.0 + #define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 4.0 + #define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 2.0 + #define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 3.0 + #define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) + #define FXAA_QUALITY__PS 9 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 4.0 + #define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) + #define FXAA_QUALITY__PS 10 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 4.0 + #define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) + #define FXAA_QUALITY__PS 11 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 4.0 + #define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.0 + #define FXAA_QUALITY__P2 1.0 + #define FXAA_QUALITY__P3 1.0 + #define FXAA_QUALITY__P4 1.0 + #define FXAA_QUALITY__P5 1.5 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +#else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif + + +/*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } +#else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x___} = -N/screenWidthInPixels + // {_y__} = -N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x___} = -2.0/screenWidthInPixels + // {_y__} = -2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x___} = 8.0/screenWidthInPixels + // {_y__} = 8.0/screenHeightInPixels + // {__z_} = -4.0/screenWidthInPixels + // {___w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - PC VERSION + +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with + #define FXAA_QUALITY__PRESET 10 +Or + #define FXAA_QUALITY__PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat lumaM = rgbyM.w; + #else + FxaaFloat lumaM = rgbyM.y; + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + #else + FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); + #endif + if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ +[reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + #if (FXAA_GREEN_AS_LUMA == 0) + asm { + tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #else + asm { + tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #endif +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + float lumaMinM = min(lumaMin, rgbyM.w); + float lumaMaxM = max(lumaMax, rgbyM.w); + #else + float lumaMinM = min(lumaMin, rgbyM.y); + float lumaMaxM = max(lumaMax, rgbyM.y); + #endif + if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; + dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + float4 rgbyA = rgbyN1 + rgbyP1; + float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; + #else + lumaNe.y += half(1.0/512.0); + dir.x = -lumaNe.y; + dir.z = -lumaNe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSw.w; + dir.z += lumaSw.w; + #else + dir.x += lumaSw.y; + dir.z += lumaSw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x -= lumaNw.w; + dir.z += lumaNw.w; + #else + dir.x -= lumaNw.y; + dir.z += lumaNw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSe.w; + dir.z -= lumaSe.w; + #else + dir.x += lumaSe.y; + dir.z -= lumaSe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #else + half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); + half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaNe = rgbyNe.w + half(1.0/512.0); + #else + half lumaNe = rgbyNe.y + half(1.0/512.0); + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaSwNegNe = lumaSw.w - lumaNe; + #else + half lumaSwNegNe = lumaSw.y - lumaNe; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); + #else + half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); + half lumaMinNwSw = min(lumaNw.y, lumaSw.y); + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; + #else + half dirZ = lumaNw.y + lumaSwNegNe; + half dirX = -lumaNw.y + lumaSwNegNe; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); + #else + dir.x = lumaSe.y + dirX; + dir.z = -lumaSe.y + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNeSe = max(lumaNe, lumaSe.w); + #else + half lumaMaxNeSe = max(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); + #else + half lumaMaxM = max(lumaMax, rgbyM.y); + half lumaMinM = min(lumaMin, rgbyM.y); + #endif +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif diff --git a/third_party/vulkan/vk_platform.h b/third_party/vulkan/vk_platform.h index 048322d93..18b913abc 100644 --- a/third_party/vulkan/vk_platform.h +++ b/third_party/vulkan/vk_platform.h @@ -2,7 +2,7 @@ // File: vk_platform.h // /* -** Copyright (c) 2014-2020 The Khronos Group Inc. +** Copyright 2014-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -58,7 +58,9 @@ extern "C" #define VKAPI_PTR #endif -#include +#if !defined(VK_NO_STDDEF_H) + #include +#endif // !defined(VK_NO_STDDEF_H) #if !defined(VK_NO_STDINT_H) #if defined(_MSC_VER) && (_MSC_VER < 1600) diff --git a/third_party/vulkan/vulkan.h b/third_party/vulkan/vulkan.h index b7716ec8e..3f7cdba58 100644 --- a/third_party/vulkan/vulkan.h +++ b/third_party/vulkan/vulkan.h @@ -2,7 +2,7 @@ #define VULKAN_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -80,6 +80,11 @@ #endif +#ifdef VK_USE_PLATFORM_SCREEN_QNX +#include +#include "vulkan_screen.h" +#endif + #ifdef VK_ENABLE_BETA_EXTENSIONS #include "vulkan_beta.h" #endif diff --git a/third_party/vulkan/vulkan_android.h b/third_party/vulkan/vulkan_android.h index 50ef85f13..a8a830673 100644 --- a/third_party/vulkan/vulkan_android.h +++ b/third_party/vulkan/vulkan_android.h @@ -2,7 +2,7 @@ #define VULKAN_ANDROID_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -44,7 +44,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( #define VK_ANDROID_external_memory_android_hardware_buffer 1 struct AHardwareBuffer; -#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3 +#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 4 #define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer" typedef struct VkAndroidHardwareBufferUsageANDROID { VkStructureType sType; @@ -90,6 +90,19 @@ typedef struct VkExternalFormatANDROID { uint64_t externalFormat; } VkExternalFormatANDROID; +typedef struct VkAndroidHardwareBufferFormatProperties2ANDROID { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + VkFormatFeatureFlags2KHR formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkAndroidHardwareBufferFormatProperties2ANDROID; + typedef VkResult (VKAPI_PTR *PFN_vkGetAndroidHardwareBufferPropertiesANDROID)(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties); typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryAndroidHardwareBufferANDROID)(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer); diff --git a/third_party/vulkan/vulkan_beta.h b/third_party/vulkan/vulkan_beta.h index 2904234a7..d2f34d1cd 100644 --- a/third_party/vulkan/vulkan_beta.h +++ b/third_party/vulkan/vulkan_beta.h @@ -2,7 +2,7 @@ #define VULKAN_BETA_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,408 +19,813 @@ extern "C" { -#define VK_KHR_deferred_host_operations 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) -#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 3 -#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" -typedef struct VkDeferredOperationInfoKHR { +#define VK_KHR_video_queue 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionParametersKHR) +#define VK_KHR_VIDEO_QUEUE_SPEC_VERSION 2 +#define VK_KHR_VIDEO_QUEUE_EXTENSION_NAME "VK_KHR_video_queue" + +typedef enum VkQueryResultStatusKHR { + VK_QUERY_RESULT_STATUS_ERROR_KHR = -1, + VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0, + VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1, + VK_QUERY_RESULT_STATUS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkQueryResultStatusKHR; + +typedef enum VkVideoCodecOperationFlagBitsKHR { + VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR = 0, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT = 0x00010000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT = 0x00020000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_EXT = 0x00000001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_EXT = 0x00000002, +#endif + VK_VIDEO_CODEC_OPERATION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodecOperationFlagBitsKHR; +typedef VkFlags VkVideoCodecOperationFlagsKHR; + +typedef enum VkVideoChromaSubsamplingFlagBitsKHR { + VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_BIT_KHR = 0, + VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0x00000001, + VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0x00000002, + VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0x00000004, + VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR = 0x00000008, + VK_VIDEO_CHROMA_SUBSAMPLING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoChromaSubsamplingFlagBitsKHR; +typedef VkFlags VkVideoChromaSubsamplingFlagsKHR; + +typedef enum VkVideoComponentBitDepthFlagBitsKHR { + VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR = 0, + VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR = 0x00000001, + VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR = 0x00000004, + VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR = 0x00000010, + VK_VIDEO_COMPONENT_BIT_DEPTH_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoComponentBitDepthFlagBitsKHR; +typedef VkFlags VkVideoComponentBitDepthFlagsKHR; + +typedef enum VkVideoCapabilityFlagBitsKHR { + VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR = 0x00000001, + VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR = 0x00000002, + VK_VIDEO_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCapabilityFlagBitsKHR; +typedef VkFlags VkVideoCapabilityFlagsKHR; + +typedef enum VkVideoSessionCreateFlagBitsKHR { + VK_VIDEO_SESSION_CREATE_DEFAULT_KHR = 0, + VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0x00000001, + VK_VIDEO_SESSION_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoSessionCreateFlagBitsKHR; +typedef VkFlags VkVideoSessionCreateFlagsKHR; +typedef VkFlags VkVideoBeginCodingFlagsKHR; +typedef VkFlags VkVideoEndCodingFlagsKHR; + +typedef enum VkVideoCodingControlFlagBitsKHR { + VK_VIDEO_CODING_CONTROL_DEFAULT_KHR = 0, + VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0x00000001, + VK_VIDEO_CODING_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodingControlFlagBitsKHR; +typedef VkFlags VkVideoCodingControlFlagsKHR; + +typedef enum VkVideoCodingQualityPresetFlagBitsKHR { + VK_VIDEO_CODING_QUALITY_PRESET_NORMAL_BIT_KHR = 0x00000001, + VK_VIDEO_CODING_QUALITY_PRESET_POWER_BIT_KHR = 0x00000002, + VK_VIDEO_CODING_QUALITY_PRESET_QUALITY_BIT_KHR = 0x00000004, + VK_VIDEO_CODING_QUALITY_PRESET_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodingQualityPresetFlagBitsKHR; +typedef VkFlags VkVideoCodingQualityPresetFlagsKHR; +typedef struct VkVideoQueueFamilyProperties2KHR { + VkStructureType sType; + void* pNext; + VkVideoCodecOperationFlagsKHR videoCodecOperations; +} VkVideoQueueFamilyProperties2KHR; + +typedef struct VkVideoProfileKHR { + VkStructureType sType; + void* pNext; + VkVideoCodecOperationFlagBitsKHR videoCodecOperation; + VkVideoChromaSubsamplingFlagsKHR chromaSubsampling; + VkVideoComponentBitDepthFlagsKHR lumaBitDepth; + VkVideoComponentBitDepthFlagsKHR chromaBitDepth; +} VkVideoProfileKHR; + +typedef struct VkVideoProfilesKHR { + VkStructureType sType; + void* pNext; + uint32_t profileCount; + const VkVideoProfileKHR* pProfiles; +} VkVideoProfilesKHR; + +typedef struct VkVideoCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoCapabilityFlagsKHR capabilityFlags; + VkDeviceSize minBitstreamBufferOffsetAlignment; + VkDeviceSize minBitstreamBufferSizeAlignment; + VkExtent2D videoPictureExtentGranularity; + VkExtent2D minExtent; + VkExtent2D maxExtent; + uint32_t maxReferencePicturesSlotsCount; + uint32_t maxReferencePicturesActiveCount; +} VkVideoCapabilitiesKHR; + +typedef struct VkPhysicalDeviceVideoFormatInfoKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags imageUsage; + const VkVideoProfilesKHR* pVideoProfiles; +} VkPhysicalDeviceVideoFormatInfoKHR; + +typedef struct VkVideoFormatPropertiesKHR { + VkStructureType sType; + void* pNext; + VkFormat format; +} VkVideoFormatPropertiesKHR; + +typedef struct VkVideoPictureResourceKHR { + VkStructureType sType; + const void* pNext; + VkOffset2D codedOffset; + VkExtent2D codedExtent; + uint32_t baseArrayLayer; + VkImageView imageViewBinding; +} VkVideoPictureResourceKHR; + +typedef struct VkVideoReferenceSlotKHR { + VkStructureType sType; + const void* pNext; + int8_t slotIndex; + const VkVideoPictureResourceKHR* pPictureResource; +} VkVideoReferenceSlotKHR; + +typedef struct VkVideoGetMemoryPropertiesKHR { VkStructureType sType; const void* pNext; - VkDeferredOperationKHR operationHandle; -} VkDeferredOperationInfoKHR; + uint32_t memoryBindIndex; + VkMemoryRequirements2* pMemoryRequirements; +} VkVideoGetMemoryPropertiesKHR; -typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); -typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); -typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); -typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); -typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef struct VkVideoBindMemoryKHR { + VkStructureType sType; + const void* pNext; + uint32_t memoryBindIndex; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkDeviceSize memorySize; +} VkVideoBindMemoryKHR; + +typedef struct VkVideoSessionCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + VkVideoSessionCreateFlagsKHR flags; + const VkVideoProfileKHR* pVideoProfile; + VkFormat pictureFormat; + VkExtent2D maxCodedExtent; + VkFormat referencePicturesFormat; + uint32_t maxReferencePicturesSlotsCount; + uint32_t maxReferencePicturesActiveCount; +} VkVideoSessionCreateInfoKHR; + +typedef struct VkVideoSessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoSessionParametersKHR videoSessionParametersTemplate; + VkVideoSessionKHR videoSession; +} VkVideoSessionParametersCreateInfoKHR; + +typedef struct VkVideoSessionParametersUpdateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t updateSequenceCount; +} VkVideoSessionParametersUpdateInfoKHR; + +typedef struct VkVideoBeginCodingInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoBeginCodingFlagsKHR flags; + VkVideoCodingQualityPresetFlagsKHR codecQualityPreset; + VkVideoSessionKHR videoSession; + VkVideoSessionParametersKHR videoSessionParameters; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotKHR* pReferenceSlots; +} VkVideoBeginCodingInfoKHR; + +typedef struct VkVideoEndCodingInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEndCodingFlagsKHR flags; +} VkVideoEndCodingInfoKHR; + +typedef struct VkVideoCodingControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoCodingControlFlagsKHR flags; +} VkVideoCodingControlInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)(VkPhysicalDevice physicalDevice, const VkVideoProfileKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionKHR)(VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession); +typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionKHR)(VkDevice device, VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetVideoSessionMemoryRequirementsKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pVideoSessionMemoryRequirementsCount, VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindVideoSessionMemoryKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t videoSessionBindMemoryCount, const VkVideoBindMemoryKHR* pVideoSessionBindMemories); +typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionParametersKHR)(VkDevice device, const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionParametersKHR* pVideoSessionParameters); +typedef VkResult (VKAPI_PTR *PFN_vkUpdateVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); +typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBeginVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoBeginCodingInfoKHR* pBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoEndCodingInfoKHR* pEndCodingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdControlVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoCodingControlInfoKHR* pCodingControlInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( - VkDevice device, - const VkAllocationCallbacks* pAllocator, - VkDeferredOperationKHR* pDeferredOperation); +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + const VkVideoProfileKHR* pVideoProfile, + VkVideoCapabilitiesKHR* pCapabilities); -VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoFormatPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, + uint32_t* pVideoFormatPropertyCount, + VkVideoFormatPropertiesKHR* pVideoFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionKHR( VkDevice device, - VkDeferredOperationKHR operation, + const VkVideoSessionCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkVideoSessionKHR* pVideoSession); + +VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionKHR( + VkDevice device, + VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkGetVideoSessionMemoryRequirementsKHR( VkDevice device, - VkDeferredOperationKHR operation); + VkVideoSessionKHR videoSession, + uint32_t* pVideoSessionMemoryRequirementsCount, + VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements); -VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkBindVideoSessionMemoryKHR( VkDevice device, - VkDeferredOperationKHR operation); + VkVideoSessionKHR videoSession, + uint32_t videoSessionBindMemoryCount, + const VkVideoBindMemoryKHR* pVideoSessionBindMemories); -VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( +VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionParametersKHR( VkDevice device, - VkDeferredOperationKHR operation); + const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkVideoSessionParametersKHR* pVideoSessionParameters); + +VKAPI_ATTR VkResult VKAPI_CALL vkUpdateVideoSessionParametersKHR( + VkDevice device, + VkVideoSessionParametersKHR videoSessionParameters, + const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); + +VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionParametersKHR( + VkDevice device, + VkVideoSessionParametersKHR videoSessionParameters, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoBeginCodingInfoKHR* pBeginInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoEndCodingInfoKHR* pEndCodingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoCodingControlInfoKHR* pCodingControlInfo); #endif -#define VK_KHR_pipeline_library 1 -#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 -#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" -typedef struct VkPipelineLibraryCreateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t libraryCount; - const VkPipeline* pLibraries; -} VkPipelineLibraryCreateInfoKHR; +#define VK_KHR_video_decode_queue 1 +#define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 2 +#define VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME "VK_KHR_video_decode_queue" - - -#define VK_KHR_ray_tracing 1 -#define VK_KHR_RAY_TRACING_SPEC_VERSION 8 -#define VK_KHR_RAY_TRACING_EXTENSION_NAME "VK_KHR_ray_tracing" - -typedef enum VkAccelerationStructureBuildTypeKHR { - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2, - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkAccelerationStructureBuildTypeKHR; -typedef union VkDeviceOrHostAddressKHR { - VkDeviceAddress deviceAddress; - void* hostAddress; -} VkDeviceOrHostAddressKHR; - -typedef union VkDeviceOrHostAddressConstKHR { - VkDeviceAddress deviceAddress; - const void* hostAddress; -} VkDeviceOrHostAddressConstKHR; - -typedef struct VkAccelerationStructureBuildOffsetInfoKHR { - uint32_t primitiveCount; - uint32_t primitiveOffset; - uint32_t firstVertex; - uint32_t transformOffset; -} VkAccelerationStructureBuildOffsetInfoKHR; - -typedef struct VkRayTracingShaderGroupCreateInfoKHR { +typedef enum VkVideoDecodeFlagBitsKHR { + VK_VIDEO_DECODE_DEFAULT_KHR = 0, + VK_VIDEO_DECODE_RESERVED_0_BIT_KHR = 0x00000001, + VK_VIDEO_DECODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoDecodeFlagBitsKHR; +typedef VkFlags VkVideoDecodeFlagsKHR; +typedef struct VkVideoDecodeInfoKHR { VkStructureType sType; const void* pNext; - VkRayTracingShaderGroupTypeKHR type; - uint32_t generalShader; - uint32_t closestHitShader; - uint32_t anyHitShader; - uint32_t intersectionShader; - const void* pShaderGroupCaptureReplayHandle; -} VkRayTracingShaderGroupCreateInfoKHR; + VkVideoDecodeFlagsKHR flags; + VkOffset2D codedOffset; + VkExtent2D codedExtent; + VkBuffer srcBuffer; + VkDeviceSize srcBufferOffset; + VkDeviceSize srcBufferRange; + VkVideoPictureResourceKHR dstPictureResource; + const VkVideoReferenceSlotKHR* pSetupReferenceSlot; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotKHR* pReferenceSlots; +} VkVideoDecodeInfoKHR; -typedef struct VkRayTracingPipelineInterfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t maxPayloadSize; - uint32_t maxAttributeSize; - uint32_t maxCallableSize; -} VkRayTracingPipelineInterfaceCreateInfoKHR; - -typedef struct VkRayTracingPipelineCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags flags; - uint32_t stageCount; - const VkPipelineShaderStageCreateInfo* pStages; - uint32_t groupCount; - const VkRayTracingShaderGroupCreateInfoKHR* pGroups; - uint32_t maxRecursionDepth; - VkPipelineLibraryCreateInfoKHR libraries; - const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface; - VkPipelineLayout layout; - VkPipeline basePipelineHandle; - int32_t basePipelineIndex; -} VkRayTracingPipelineCreateInfoKHR; - -typedef struct VkAccelerationStructureGeometryTrianglesDataKHR { - VkStructureType sType; - const void* pNext; - VkFormat vertexFormat; - VkDeviceOrHostAddressConstKHR vertexData; - VkDeviceSize vertexStride; - VkIndexType indexType; - VkDeviceOrHostAddressConstKHR indexData; - VkDeviceOrHostAddressConstKHR transformData; -} VkAccelerationStructureGeometryTrianglesDataKHR; - -typedef struct VkAccelerationStructureGeometryAabbsDataKHR { - VkStructureType sType; - const void* pNext; - VkDeviceOrHostAddressConstKHR data; - VkDeviceSize stride; -} VkAccelerationStructureGeometryAabbsDataKHR; - -typedef struct VkAccelerationStructureGeometryInstancesDataKHR { - VkStructureType sType; - const void* pNext; - VkBool32 arrayOfPointers; - VkDeviceOrHostAddressConstKHR data; -} VkAccelerationStructureGeometryInstancesDataKHR; - -typedef union VkAccelerationStructureGeometryDataKHR { - VkAccelerationStructureGeometryTrianglesDataKHR triangles; - VkAccelerationStructureGeometryAabbsDataKHR aabbs; - VkAccelerationStructureGeometryInstancesDataKHR instances; -} VkAccelerationStructureGeometryDataKHR; - -typedef struct VkAccelerationStructureGeometryKHR { - VkStructureType sType; - const void* pNext; - VkGeometryTypeKHR geometryType; - VkAccelerationStructureGeometryDataKHR geometry; - VkGeometryFlagsKHR flags; -} VkAccelerationStructureGeometryKHR; - -typedef struct VkAccelerationStructureBuildGeometryInfoKHR { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureTypeKHR type; - VkBuildAccelerationStructureFlagsKHR flags; - VkBool32 update; - VkAccelerationStructureKHR srcAccelerationStructure; - VkAccelerationStructureKHR dstAccelerationStructure; - VkBool32 geometryArrayOfPointers; - uint32_t geometryCount; - const VkAccelerationStructureGeometryKHR* const* ppGeometries; - VkDeviceOrHostAddressKHR scratchData; -} VkAccelerationStructureBuildGeometryInfoKHR; - -typedef struct VkAccelerationStructureCreateGeometryTypeInfoKHR { - VkStructureType sType; - const void* pNext; - VkGeometryTypeKHR geometryType; - uint32_t maxPrimitiveCount; - VkIndexType indexType; - uint32_t maxVertexCount; - VkFormat vertexFormat; - VkBool32 allowsTransforms; -} VkAccelerationStructureCreateGeometryTypeInfoKHR; - -typedef struct VkAccelerationStructureCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkDeviceSize compactedSize; - VkAccelerationStructureTypeKHR type; - VkBuildAccelerationStructureFlagsKHR flags; - uint32_t maxGeometryCount; - const VkAccelerationStructureCreateGeometryTypeInfoKHR* pGeometryInfos; - VkDeviceAddress deviceAddress; -} VkAccelerationStructureCreateInfoKHR; - -typedef struct VkAccelerationStructureMemoryRequirementsInfoKHR { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureMemoryRequirementsTypeKHR type; - VkAccelerationStructureBuildTypeKHR buildType; - VkAccelerationStructureKHR accelerationStructure; -} VkAccelerationStructureMemoryRequirementsInfoKHR; - -typedef struct VkPhysicalDeviceRayTracingFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 rayTracing; - VkBool32 rayTracingShaderGroupHandleCaptureReplay; - VkBool32 rayTracingShaderGroupHandleCaptureReplayMixed; - VkBool32 rayTracingAccelerationStructureCaptureReplay; - VkBool32 rayTracingIndirectTraceRays; - VkBool32 rayTracingIndirectAccelerationStructureBuild; - VkBool32 rayTracingHostAccelerationStructureCommands; - VkBool32 rayQuery; - VkBool32 rayTracingPrimitiveCulling; -} VkPhysicalDeviceRayTracingFeaturesKHR; - -typedef struct VkPhysicalDeviceRayTracingPropertiesKHR { - VkStructureType sType; - void* pNext; - uint32_t shaderGroupHandleSize; - uint32_t maxRecursionDepth; - uint32_t maxShaderGroupStride; - uint32_t shaderGroupBaseAlignment; - uint64_t maxGeometryCount; - uint64_t maxInstanceCount; - uint64_t maxPrimitiveCount; - uint32_t maxDescriptorSetAccelerationStructures; - uint32_t shaderGroupHandleCaptureReplaySize; -} VkPhysicalDeviceRayTracingPropertiesKHR; - -typedef struct VkAccelerationStructureDeviceAddressInfoKHR { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureKHR accelerationStructure; -} VkAccelerationStructureDeviceAddressInfoKHR; - -typedef struct VkAccelerationStructureVersionKHR { - VkStructureType sType; - const void* pNext; - const uint8_t* versionData; -} VkAccelerationStructureVersionKHR; - -typedef struct VkStridedBufferRegionKHR { - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize stride; - VkDeviceSize size; -} VkStridedBufferRegionKHR; - -typedef struct VkTraceRaysIndirectCommandKHR { - uint32_t width; - uint32_t height; - uint32_t depth; -} VkTraceRaysIndirectCommandKHR; - -typedef struct VkCopyAccelerationStructureToMemoryInfoKHR { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureKHR src; - VkDeviceOrHostAddressKHR dst; - VkCopyAccelerationStructureModeKHR mode; -} VkCopyAccelerationStructureToMemoryInfoKHR; - -typedef struct VkCopyMemoryToAccelerationStructureInfoKHR { - VkStructureType sType; - const void* pNext; - VkDeviceOrHostAddressConstKHR src; - VkAccelerationStructureKHR dst; - VkCopyAccelerationStructureModeKHR mode; -} VkCopyMemoryToAccelerationStructureInfoKHR; - -typedef struct VkCopyAccelerationStructureInfoKHR { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureKHR src; - VkAccelerationStructureKHR dst; - VkCopyAccelerationStructureModeKHR mode; -} VkCopyAccelerationStructureInfoKHR; - -typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureKHR)(VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); -typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsKHR)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo, VkMemoryRequirements2* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos); -typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureIndirectKHR)(VkCommandBuffer commandBuffer, const VkAccelerationStructureBuildGeometryInfoKHR* pInfo, VkBuffer indirectBuffer, VkDeviceSize indirectOffset, uint32_t indirectStride); -typedef VkResult (VKAPI_PTR *PFN_vkBuildAccelerationStructureKHR)(VkDevice device, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos); -typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureKHR)(VkDevice device, const VkCopyAccelerationStructureInfoKHR* pInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureToMemoryKHR)(VkDevice device, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToAccelerationStructureKHR)(VkDevice device, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); -typedef VkResult (VKAPI_PTR *PFN_vkWriteAccelerationStructuresPropertiesKHR)(VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo); -typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); -typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); -typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysKHR)(VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, const VkStridedBufferRegionKHR* pHitShaderBindingTable, const VkStridedBufferRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); -typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesKHR)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); -typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetAccelerationStructureDeviceAddressKHR)(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirectKHR)(VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, const VkStridedBufferRegionKHR* pHitShaderBindingTable, const VkStridedBufferRegionKHR* pCallableShaderBindingTable, VkBuffer buffer, VkDeviceSize offset); -typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(VkDevice device, const VkAccelerationStructureVersionKHR* version); +typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pFrameInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR( - VkDevice device, - const VkAccelerationStructureCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkAccelerationStructureKHR* pAccelerationStructure); - -VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsKHR( - VkDevice device, - const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo, - VkMemoryRequirements2* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureKHR( +VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR( VkCommandBuffer commandBuffer, - uint32_t infoCount, - const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, - const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos); - -VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureIndirectKHR( - VkCommandBuffer commandBuffer, - const VkAccelerationStructureBuildGeometryInfoKHR* pInfo, - VkBuffer indirectBuffer, - VkDeviceSize indirectOffset, - uint32_t indirectStride); - -VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructureKHR( - VkDevice device, - uint32_t infoCount, - const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, - const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos); - -VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR( - VkDevice device, - const VkCopyAccelerationStructureInfoKHR* pInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR( - VkDevice device, - const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR( - VkDevice device, - const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( - VkDevice device, - uint32_t accelerationStructureCount, - const VkAccelerationStructureKHR* pAccelerationStructures, - VkQueryType queryType, - size_t dataSize, - void* pData, - size_t stride); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR( - VkCommandBuffer commandBuffer, - const VkCopyAccelerationStructureInfoKHR* pInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR( - VkCommandBuffer commandBuffer, - const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR( - VkCommandBuffer commandBuffer, - const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( - VkCommandBuffer commandBuffer, - const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, - const VkStridedBufferRegionKHR* pMissShaderBindingTable, - const VkStridedBufferRegionKHR* pHitShaderBindingTable, - const VkStridedBufferRegionKHR* pCallableShaderBindingTable, - uint32_t width, - uint32_t height, - uint32_t depth); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( - VkDevice device, - VkPipelineCache pipelineCache, - uint32_t createInfoCount, - const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkPipeline* pPipelines); - -VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR( - VkDevice device, - const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( - VkDevice device, - VkPipeline pipeline, - uint32_t firstGroup, - uint32_t groupCount, - size_t dataSize, - void* pData); - -VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( - VkCommandBuffer commandBuffer, - const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, - const VkStridedBufferRegionKHR* pMissShaderBindingTable, - const VkStridedBufferRegionKHR* pHitShaderBindingTable, - const VkStridedBufferRegionKHR* pCallableShaderBindingTable, - VkBuffer buffer, - VkDeviceSize offset); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR( - VkDevice device, - const VkAccelerationStructureVersionKHR* version); + const VkVideoDecodeInfoKHR* pFrameInfo); #endif + +#define VK_KHR_portability_subset 1 +#define VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION 1 +#define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" +typedef struct VkPhysicalDevicePortabilitySubsetFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 constantAlphaColorBlendFactors; + VkBool32 events; + VkBool32 imageViewFormatReinterpretation; + VkBool32 imageViewFormatSwizzle; + VkBool32 imageView2DOn3DImage; + VkBool32 multisampleArrayImage; + VkBool32 mutableComparisonSamplers; + VkBool32 pointPolygons; + VkBool32 samplerMipLodBias; + VkBool32 separateStencilMaskRef; + VkBool32 shaderSampleRateInterpolationFunctions; + VkBool32 tessellationIsolines; + VkBool32 tessellationPointMode; + VkBool32 triangleFans; + VkBool32 vertexAttributeAccessBeyondStride; +} VkPhysicalDevicePortabilitySubsetFeaturesKHR; + +typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t minVertexInputBindingStrideAlignment; +} VkPhysicalDevicePortabilitySubsetPropertiesKHR; + + + +#define VK_KHR_video_encode_queue 1 +#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 3 +#define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue" + +typedef enum VkVideoEncodeFlagBitsKHR { + VK_VIDEO_ENCODE_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_RESERVED_0_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeFlagBitsKHR; +typedef VkFlags VkVideoEncodeFlagsKHR; + +typedef enum VkVideoEncodeRateControlFlagBitsKHR { + VK_VIDEO_ENCODE_RATE_CONTROL_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_RATE_CONTROL_RESET_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_RATE_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeRateControlFlagBitsKHR; +typedef VkFlags VkVideoEncodeRateControlFlagsKHR; + +typedef enum VkVideoEncodeRateControlModeFlagBitsKHR { + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR = 0, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 1, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 2, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeRateControlModeFlagBitsKHR; +typedef VkFlags VkVideoEncodeRateControlModeFlagsKHR; +typedef struct VkVideoEncodeInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeFlagsKHR flags; + uint32_t qualityLevel; + VkExtent2D codedExtent; + VkBuffer dstBitstreamBuffer; + VkDeviceSize dstBitstreamBufferOffset; + VkDeviceSize dstBitstreamBufferMaxRange; + VkVideoPictureResourceKHR srcPictureResource; + const VkVideoReferenceSlotKHR* pSetupReferenceSlot; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotKHR* pReferenceSlots; +} VkVideoEncodeInfoKHR; + +typedef struct VkVideoEncodeRateControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeRateControlFlagsKHR flags; + VkVideoEncodeRateControlModeFlagBitsKHR rateControlMode; + uint32_t averageBitrate; + uint16_t peakToAverageBitrateRatio; + uint16_t frameRateNumerator; + uint16_t frameRateDenominator; + uint32_t virtualBufferSizeInMs; +} VkVideoEncodeRateControlInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdEncodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR( + VkCommandBuffer commandBuffer, + const VkVideoEncodeInfoKHR* pEncodeInfo); +#endif + + +#define VK_EXT_video_encode_h264 1 +#include "vk_video/vulkan_video_codec_h264std.h" +#include "vk_video/vulkan_video_codec_h264std_encode.h" +#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 2 +#define VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_EXT_video_encode_h264" + +typedef enum VkVideoEncodeH264CapabilityFlagBitsEXT { + VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BI_PRED_IMPLICIT_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT = 0x00000020, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0x00000040, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0x00000080, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0x00000100, + VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT = 0x00000200, + VK_VIDEO_ENCODE_H264_CAPABILITY_EVENLY_DISTRIBUTED_SLICE_SIZE_BIT_EXT = 0x00000400, + VK_VIDEO_ENCODE_H264_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264CapabilityFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264CapabilityFlagsEXT; + +typedef enum VkVideoEncodeH264InputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264InputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264InputModeFlagsEXT; + +typedef enum VkVideoEncodeH264OutputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264OutputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264OutputModeFlagsEXT; + +typedef enum VkVideoEncodeH264CreateFlagBitsEXT { + VK_VIDEO_ENCODE_H264_CREATE_DEFAULT_EXT = 0, + VK_VIDEO_ENCODE_H264_CREATE_RESERVED_0_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264CreateFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264CreateFlagsEXT; +typedef struct VkVideoEncodeH264CapabilitiesEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH264CapabilityFlagsEXT flags; + VkVideoEncodeH264InputModeFlagsEXT inputModeFlags; + VkVideoEncodeH264OutputModeFlagsEXT outputModeFlags; + VkExtent2D minPictureSizeInMbs; + VkExtent2D maxPictureSizeInMbs; + VkExtent2D inputImageDataAlignment; + uint8_t maxNumL0ReferenceForP; + uint8_t maxNumL0ReferenceForB; + uint8_t maxNumL1Reference; + uint8_t qualityLevelCount; + VkExtensionProperties stdExtensionVersion; +} VkVideoEncodeH264CapabilitiesEXT; + +typedef struct VkVideoEncodeH264SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH264CreateFlagsEXT flags; + VkExtent2D maxPictureSizeInMbs; + const VkExtensionProperties* pStdExtensionVersion; +} VkVideoEncodeH264SessionCreateInfoEXT; + +typedef struct VkVideoEncodeH264SessionParametersAddInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t spsStdCount; + const StdVideoH264SequenceParameterSet* pSpsStd; + uint32_t ppsStdCount; + const StdVideoH264PictureParameterSet* pPpsStd; +} VkVideoEncodeH264SessionParametersAddInfoEXT; + +typedef struct VkVideoEncodeH264SessionParametersCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxSpsStdCount; + uint32_t maxPpsStdCount; + const VkVideoEncodeH264SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoEncodeH264SessionParametersCreateInfoEXT; + +typedef struct VkVideoEncodeH264DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + int8_t slotIndex; + const StdVideoEncodeH264PictureInfo* pStdPictureInfo; +} VkVideoEncodeH264DpbSlotInfoEXT; + +typedef struct VkVideoEncodeH264NaluSliceEXT { + VkStructureType sType; + const void* pNext; + const StdVideoEncodeH264SliceHeader* pSliceHeaderStd; + uint32_t mbCount; + uint8_t refFinalList0EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pRefFinalList0Entries; + uint8_t refFinalList1EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pRefFinalList1Entries; + uint32_t precedingNaluBytes; + uint8_t minQp; + uint8_t maxQp; +} VkVideoEncodeH264NaluSliceEXT; + +typedef struct VkVideoEncodeH264VclFrameInfoEXT { + VkStructureType sType; + const void* pNext; + uint8_t refDefaultFinalList0EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pRefDefaultFinalList0Entries; + uint8_t refDefaultFinalList1EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pRefDefaultFinalList1Entries; + uint32_t naluSliceEntryCount; + const VkVideoEncodeH264NaluSliceEXT* pNaluSliceEntries; + const VkVideoEncodeH264DpbSlotInfoEXT* pCurrentPictureInfo; +} VkVideoEncodeH264VclFrameInfoEXT; + +typedef struct VkVideoEncodeH264EmitPictureParametersEXT { + VkStructureType sType; + const void* pNext; + uint8_t spsId; + VkBool32 emitSpsEnable; + uint32_t ppsIdEntryCount; + const uint8_t* ppsIdEntries; +} VkVideoEncodeH264EmitPictureParametersEXT; + +typedef struct VkVideoEncodeH264ProfileEXT { + VkStructureType sType; + const void* pNext; + StdVideoH264ProfileIdc stdProfileIdc; +} VkVideoEncodeH264ProfileEXT; + + + +#define VK_EXT_video_encode_h265 1 +#include "vk_video/vulkan_video_codec_h265std.h" +#include "vk_video/vulkan_video_codec_h265std_encode.h" +#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 2 +#define VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_EXT_video_encode_h265" +typedef VkFlags VkVideoEncodeH265CapabilityFlagsEXT; + +typedef enum VkVideoEncodeH265InputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265InputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265InputModeFlagsEXT; + +typedef enum VkVideoEncodeH265OutputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265OutputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265OutputModeFlagsEXT; +typedef VkFlags VkVideoEncodeH265CreateFlagsEXT; + +typedef enum VkVideoEncodeH265CtbSizeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_CTB_SIZE_8_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H265_CTB_SIZE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265CtbSizeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265CtbSizeFlagsEXT; +typedef struct VkVideoEncodeH265CapabilitiesEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH265CapabilityFlagsEXT flags; + VkVideoEncodeH265InputModeFlagsEXT inputModeFlags; + VkVideoEncodeH265OutputModeFlagsEXT outputModeFlags; + VkVideoEncodeH265CtbSizeFlagsEXT ctbSizes; + VkExtent2D inputImageDataAlignment; + uint8_t maxNumL0ReferenceForP; + uint8_t maxNumL0ReferenceForB; + uint8_t maxNumL1Reference; + uint8_t maxNumSubLayers; + uint8_t qualityLevelCount; + VkExtensionProperties stdExtensionVersion; +} VkVideoEncodeH265CapabilitiesEXT; + +typedef struct VkVideoEncodeH265SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH265CreateFlagsEXT flags; + const VkExtensionProperties* pStdExtensionVersion; +} VkVideoEncodeH265SessionCreateInfoEXT; + +typedef struct VkVideoEncodeH265SessionParametersAddInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t vpsStdCount; + const StdVideoH265VideoParameterSet* pVpsStd; + uint32_t spsStdCount; + const StdVideoH265SequenceParameterSet* pSpsStd; + uint32_t ppsStdCount; + const StdVideoH265PictureParameterSet* pPpsStd; +} VkVideoEncodeH265SessionParametersAddInfoEXT; + +typedef struct VkVideoEncodeH265SessionParametersCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxVpsStdCount; + uint32_t maxSpsStdCount; + uint32_t maxPpsStdCount; + const VkVideoEncodeH265SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoEncodeH265SessionParametersCreateInfoEXT; + +typedef struct VkVideoEncodeH265DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + int8_t slotIndex; + const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeH265DpbSlotInfoEXT; + +typedef struct VkVideoEncodeH265ReferenceListsEXT { + VkStructureType sType; + const void* pNext; + uint8_t referenceList0EntryCount; + const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList0Entries; + uint8_t referenceList1EntryCount; + const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList1Entries; + const StdVideoEncodeH265ReferenceModifications* pReferenceModifications; +} VkVideoEncodeH265ReferenceListsEXT; + +typedef struct VkVideoEncodeH265NaluSliceEXT { + VkStructureType sType; + const void* pNext; + uint32_t ctbCount; + const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists; + const StdVideoEncodeH265SliceHeader* pSliceHeaderStd; +} VkVideoEncodeH265NaluSliceEXT; + +typedef struct VkVideoEncodeH265VclFrameInfoEXT { + VkStructureType sType; + const void* pNext; + const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists; + uint32_t naluSliceEntryCount; + const VkVideoEncodeH265NaluSliceEXT* pNaluSliceEntries; + const StdVideoEncodeH265PictureInfo* pCurrentPictureInfo; +} VkVideoEncodeH265VclFrameInfoEXT; + +typedef struct VkVideoEncodeH265EmitPictureParametersEXT { + VkStructureType sType; + const void* pNext; + uint8_t vpsId; + uint8_t spsId; + VkBool32 emitVpsEnable; + VkBool32 emitSpsEnable; + uint32_t ppsIdEntryCount; + const uint8_t* ppsIdEntries; +} VkVideoEncodeH265EmitPictureParametersEXT; + +typedef struct VkVideoEncodeH265ProfileEXT { + VkStructureType sType; + const void* pNext; + StdVideoH265ProfileIdc stdProfileIdc; +} VkVideoEncodeH265ProfileEXT; + + + +#define VK_EXT_video_decode_h264 1 +#include "vk_video/vulkan_video_codec_h264std_decode.h" +#define VK_EXT_VIDEO_DECODE_H264_SPEC_VERSION 3 +#define VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME "VK_EXT_video_decode_h264" + +typedef enum VkVideoDecodeH264PictureLayoutFlagBitsEXT { + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_EXT = 0, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_EXT = 0x00000001, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_EXT = 0x00000002, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoDecodeH264PictureLayoutFlagBitsEXT; +typedef VkFlags VkVideoDecodeH264PictureLayoutFlagsEXT; +typedef VkFlags VkVideoDecodeH264CreateFlagsEXT; +typedef struct VkVideoDecodeH264ProfileEXT { + VkStructureType sType; + const void* pNext; + StdVideoH264ProfileIdc stdProfileIdc; + VkVideoDecodeH264PictureLayoutFlagsEXT pictureLayout; +} VkVideoDecodeH264ProfileEXT; + +typedef struct VkVideoDecodeH264CapabilitiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxLevel; + VkOffset2D fieldOffsetGranularity; + VkExtensionProperties stdExtensionVersion; +} VkVideoDecodeH264CapabilitiesEXT; + +typedef struct VkVideoDecodeH264SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoDecodeH264CreateFlagsEXT flags; + const VkExtensionProperties* pStdExtensionVersion; +} VkVideoDecodeH264SessionCreateInfoEXT; + +typedef struct VkVideoDecodeH264SessionParametersAddInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t spsStdCount; + const StdVideoH264SequenceParameterSet* pSpsStd; + uint32_t ppsStdCount; + const StdVideoH264PictureParameterSet* pPpsStd; +} VkVideoDecodeH264SessionParametersAddInfoEXT; + +typedef struct VkVideoDecodeH264SessionParametersCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxSpsStdCount; + uint32_t maxPpsStdCount; + const VkVideoDecodeH264SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoDecodeH264SessionParametersCreateInfoEXT; + +typedef struct VkVideoDecodeH264PictureInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264PictureInfo* pStdPictureInfo; + uint32_t slicesCount; + const uint32_t* pSlicesDataOffsets; +} VkVideoDecodeH264PictureInfoEXT; + +typedef struct VkVideoDecodeH264MvcEXT { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264Mvc* pStdMvc; +} VkVideoDecodeH264MvcEXT; + +typedef struct VkVideoDecodeH264DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeH264DpbSlotInfoEXT; + + + +#define VK_EXT_video_decode_h265 1 +#include "vk_video/vulkan_video_codec_h265std_decode.h" +#define VK_EXT_VIDEO_DECODE_H265_SPEC_VERSION 1 +#define VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME "VK_EXT_video_decode_h265" +typedef VkFlags VkVideoDecodeH265CreateFlagsEXT; +typedef struct VkVideoDecodeH265ProfileEXT { + VkStructureType sType; + const void* pNext; + StdVideoH265ProfileIdc stdProfileIdc; +} VkVideoDecodeH265ProfileEXT; + +typedef struct VkVideoDecodeH265CapabilitiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxLevel; + VkExtensionProperties stdExtensionVersion; +} VkVideoDecodeH265CapabilitiesEXT; + +typedef struct VkVideoDecodeH265SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoDecodeH265CreateFlagsEXT flags; + const VkExtensionProperties* pStdExtensionVersion; +} VkVideoDecodeH265SessionCreateInfoEXT; + +typedef struct VkVideoDecodeH265SessionParametersAddInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t spsStdCount; + const StdVideoH265SequenceParameterSet* pSpsStd; + uint32_t ppsStdCount; + const StdVideoH265PictureParameterSet* pPpsStd; +} VkVideoDecodeH265SessionParametersAddInfoEXT; + +typedef struct VkVideoDecodeH265SessionParametersCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxSpsStdCount; + uint32_t maxPpsStdCount; + const VkVideoDecodeH265SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoDecodeH265SessionParametersCreateInfoEXT; + +typedef struct VkVideoDecodeH265PictureInfoEXT { + VkStructureType sType; + const void* pNext; + StdVideoDecodeH265PictureInfo* pStdPictureInfo; + uint32_t slicesCount; + const uint32_t* pSlicesDataOffsets; +} VkVideoDecodeH265PictureInfoEXT; + +typedef struct VkVideoDecodeH265DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeH265DpbSlotInfoEXT; + + #ifdef __cplusplus } #endif diff --git a/third_party/vulkan/vulkan_core.h b/third_party/vulkan/vulkan_core.h index ae2140997..2bd3f779e 100644 --- a/third_party/vulkan/vulkan_core.h +++ b/third_party/vulkan/vulkan_core.h @@ -2,7 +2,7 @@ #define VULKAN_CORE_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -25,35 +25,71 @@ extern "C" { #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; -#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE) -#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) - #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; -#else - #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; -#endif +#ifndef VK_USE_64_BIT_PTR_DEFINES + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VK_USE_64_BIT_PTR_DEFINES 1 + #else + #define VK_USE_64_BIT_PTR_DEFINES 0 + #endif #endif + +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) + #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)) + #define VK_NULL_HANDLE nullptr + #else + #define VK_NULL_HANDLE ((void*)0) + #endif + #else + #define VK_NULL_HANDLE 0ULL + #endif +#endif +#ifndef VK_NULL_HANDLE + #define VK_NULL_HANDLE 0 +#endif + + +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; + #else + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; + #endif +#endif + +// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. #define VK_MAKE_VERSION(major, minor, patch) \ ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) // DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. //#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 +#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) + // Vulkan 1.0 version number -#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)// Patch version should always be set to 0 +#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 148 +#define VK_HEADER_VERSION 198 // Complete version of this file -#define VK_HEADER_VERSION_COMPLETE VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 2, VK_HEADER_VERSION) +// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. #define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) -#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) -#define VK_NULL_HANDLE 0 +// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. +#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) + +#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29) +#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU) +#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +#define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) typedef uint32_t VkBool32; typedef uint64_t VkDeviceAddress; typedef uint64_t VkDeviceSize; @@ -84,21 +120,21 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) +#define VK_UUID_SIZE 16U #define VK_ATTACHMENT_UNUSED (~0U) -#define VK_FALSE 0 -#define VK_LOD_CLAMP_NONE 1000.0f +#define VK_FALSE 0U +#define VK_LOD_CLAMP_NONE 1000.0F #define VK_QUEUE_FAMILY_IGNORED (~0U) #define VK_REMAINING_ARRAY_LAYERS (~0U) #define VK_REMAINING_MIP_LEVELS (~0U) #define VK_SUBPASS_EXTERNAL (~0U) -#define VK_TRUE 1 +#define VK_TRUE 1U #define VK_WHOLE_SIZE (~0ULL) -#define VK_MAX_MEMORY_TYPES 32 -#define VK_MAX_MEMORY_HEAPS 16 -#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256 -#define VK_UUID_SIZE 16 -#define VK_MAX_EXTENSION_NAME_SIZE 256 -#define VK_MAX_DESCRIPTION_SIZE 256 +#define VK_MAX_MEMORY_TYPES 32U +#define VK_MAX_MEMORY_HEAPS 16U +#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256U +#define VK_MAX_EXTENSION_NAME_SIZE 256U +#define VK_MAX_DESCRIPTION_SIZE 256U typedef enum VkResult { VK_SUCCESS = 0, @@ -131,7 +167,6 @@ typedef enum VkResult { VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, VK_ERROR_INVALID_SHADER_NV = -1000012000, - VK_ERROR_INCOMPATIBLE_VERSION_KHR = -1000150000, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, VK_ERROR_NOT_PERMITTED_EXT = -1000174001, VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, @@ -335,15 +370,159 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000, VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001, VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR = 1000023000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR = 1000023001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR = 1000023002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR = 1000023003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR = 1000023004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR = 1000023005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR = 1000023008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR = 1000023009, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR = 1000023010, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR = 1000023011, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000023012, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR = 1000023013, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR = 1000023015, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR = 1000024000, +#endif VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, + VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX = 1000029000, + VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX = 1000029001, + VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX = 1000029002, VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000, VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT = 1000038000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT = 1000038001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000038002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT = 1000038004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT = 1000038006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT = 1000038007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT = 1000038008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_CREATE_INFO_EXT = 1000039001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000039002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000039003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT = 1000039004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT = 1000039005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_EXT = 1000039006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_EXT = 1000039007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_EXT = 1000039008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_EXT = 1000039009, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT = 1000040000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_CREATE_INFO_EXT = 1000040001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT = 1000040002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT = 1000040003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT = 1000040004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000040005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000040006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT = 1000040007, +#endif VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + VK_STRUCTURE_TYPE_RENDERING_INFO_KHR = 1000044000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR = 1000044001, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR = 1000044002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = 1000044003, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = 1000044004, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, @@ -425,6 +604,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003, VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001, VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002, @@ -438,37 +618,44 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, - VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR = 1000165006, - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000165007, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000, - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR = 1000150001, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006, - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR = 1000150008, - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR = 1000150009, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR = 1000150009, VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010, VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011, VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR = 1000150013, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR = 1000150014, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR = 1000150013, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR = 1000150014, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR = 1000347000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR = 1000347001, VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015, VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016, - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013, VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000, - VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004, VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005, + VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT = 1000158006, VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001, +#endif VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002, @@ -478,6 +665,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003, VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004, VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005, + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009, VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011, @@ -494,6 +683,27 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000, VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT = 1000187000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_CREATE_INFO_EXT = 1000187001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000187002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000187003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT = 1000187004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT = 1000187005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT = 1000187006, +#endif VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, @@ -520,6 +730,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000, VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001, VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = 1000215000, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001, @@ -527,8 +738,14 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = 1000225000, VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = 1000225001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = 1000225002, + VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR = 1000226003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR = 1000226004, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000, VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001, @@ -538,6 +755,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = 1000245000, VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT = 1000247000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR = 1000248000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000, VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249002, @@ -546,6 +764,9 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV = 1000250002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT = 1000251000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT = 1000252000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT = 1000254000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT = 1000254001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT = 1000254002, VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT = 1000255000, VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002, VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001, @@ -556,13 +777,13 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT = 1000267000, - VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR = 1000268000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000, VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = 1000276000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, @@ -572,29 +793,123 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV = 1000277005, VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV = 1000278000, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV = 1000278001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR = 1000280000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR = 1000280001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = 1000281001, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, + VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001, VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, + VK_STRUCTURE_TYPE_PRESENT_ID_KHR = 1000294000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = 1000295000, VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = 1000295001, VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT = 1000295002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = 1000297000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR = 1000299000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001, +#endif VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR = 1000314000, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR = 1000314001, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR = 1000314002, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR = 1000314003, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR = 1000314004, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR = 1000314005, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR = 1000314006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = 1000314007, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR = 1000323000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = 1000325000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001, + VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = 1000335000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR = 1000337000, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR = 1000337001, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR = 1000337002, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR = 1000337003, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR = 1000337004, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR = 1000337005, + VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR = 1000337006, + VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR = 1000337007, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = 1000337008, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = 1000337009, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = 1000337010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000, VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = 1000351000, + VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = 1000351002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000, + VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001, + VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR = 1000360000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000, + VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001, + VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002, + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365000, + VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365001, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1000366000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1000366001, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1000366002, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1000366003, + VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA = 1000366004, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA = 1000366005, + VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA = 1000366006, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA = 1000366007, + VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA = 1000366008, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA = 1000366009, + VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI = 1000369000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI = 1000369001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI = 1000369002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI = 1000370000, + VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV = 1000371000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT = 1000377000, + VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX = 1000378000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT = 1000381000, + VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = 1000388000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = 1000388001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000, + VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR = 1000413000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = 1000413001, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = 1000413002, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = 1000413003, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD, VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, @@ -675,8 +990,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT, - VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR, - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, @@ -728,11 +1041,32 @@ typedef enum VkImageLayout { VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR = 1000024000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR = 1000024001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR = 1000024002, +#endif VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, - VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, + VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR = 1000299000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR = 1000299001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR = 1000299002, +#endif + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = 1000314000, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = 1000314001, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, @@ -774,33 +1108,43 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_OBJECT_TYPE_VIDEO_SESSION_KHR = 1000023000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR = 1000023001, +#endif + VK_OBJECT_TYPE_CU_MODULE_NVX = 1000029000, + VK_OBJECT_TYPE_CU_FUNCTION_NVX = 1000029001, VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, - VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000165000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000, VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000, VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = 1000295000, + VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, - VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR, VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF } VkObjectType; +typedef enum VkPipelineCacheHeaderVersion { + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheHeaderVersion; + typedef enum VkVendorId { VK_VENDOR_ID_VIV = 0x10001, VK_VENDOR_ID_VSI = 0x10002, VK_VENDOR_ID_KAZAN = 0x10003, VK_VENDOR_ID_CODEPLAY = 0x10004, VK_VENDOR_ID_MESA = 0x10005, + VK_VENDOR_ID_POCL = 0x10006, VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF } VkVendorId; -typedef enum VkPipelineCacheHeaderVersion { - VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, - VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF -} VkPipelineCacheHeaderVersion; - typedef enum VkSystemAllocationScope { VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1, @@ -1057,6 +1401,12 @@ typedef enum VkFormat { VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = 1000066011, VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = 1000066012, VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = 1000066013, + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT = 1000330000, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT = 1000330001, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT = 1000330002, + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT = 1000330003, + VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = 1000340000, + VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = 1000340001, VK_FORMAT_G8B8G8R8_422_UNORM_KHR = VK_FORMAT_G8B8G8R8_422_UNORM, VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM, VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, @@ -1121,12 +1471,18 @@ typedef enum VkQueryType { VK_QUERY_TYPE_OCCLUSION = 0, VK_QUERY_TYPE_PIPELINE_STATISTICS = 1, VK_QUERY_TYPE_TIMESTAMP = 2, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR = 1000023000, +#endif VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004, VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000, - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000165000, - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150001, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000, +#endif VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF } VkQueryType; @@ -1261,9 +1617,11 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, + VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000, VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004, VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, + VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000, VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000, VK_DYNAMIC_STATE_CULL_MODE_EXT = 1000267000, VK_DYNAMIC_STATE_FRONT_FACE_EXT = 1000267001, @@ -1277,6 +1635,13 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT = 1000267009, VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT = 1000267010, VK_DYNAMIC_STATE_STENCIL_OP_EXT = 1000267011, + VK_DYNAMIC_STATE_VERTEX_INPUT_EXT = 1000352000, + VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT = 1000377000, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT = 1000377001, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT = 1000377002, + VK_DYNAMIC_STATE_LOGIC_OP_EXT = 1000377003, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT = 1000377004, + VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT = 1000381000, VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF } VkDynamicState; @@ -1396,8 +1761,9 @@ typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000, - VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000165000, - VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = 1000351000, VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF } VkDescriptorType; @@ -1405,13 +1771,16 @@ typedef enum VkAttachmentLoadOp { VK_ATTACHMENT_LOAD_OP_LOAD = 0, VK_ATTACHMENT_LOAD_OP_CLEAR = 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, + VK_ATTACHMENT_LOAD_OP_NONE_EXT = 1000400000, VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentLoadOp; typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_STORE = 0, VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, - VK_ATTACHMENT_STORE_OP_NONE_QCOM = 1000301000, + VK_ATTACHMENT_STORE_OP_NONE_KHR = 1000301000, + VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE_KHR, + VK_ATTACHMENT_STORE_OP_NONE_EXT = VK_ATTACHMENT_STORE_OP_NONE_KHR, VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentStoreOp; @@ -1419,6 +1788,7 @@ typedef enum VkPipelineBindPoint { VK_PIPELINE_BIND_POINT_GRAPHICS = 0, VK_PIPELINE_BIND_POINT_COMPUTE = 1, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, + VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF } VkPipelineBindPoint; @@ -1469,10 +1839,12 @@ typedef enum VkAccessFlagBits { VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000, - VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000, VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000, VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000, VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000, + VK_ACCESS_NONE_KHR = 0, + VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -1523,8 +1895,21 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000, +#endif VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000, VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000, + VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000, +#endif VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT, @@ -1587,8 +1972,28 @@ typedef enum VkImageUsageFlagBits { VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, - VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00000400, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00000800, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR = 0x00001000, +#endif VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200, + VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00000100, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00002000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00004000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR = 0x00008000, +#endif + VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI = 0x00040000, + VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageUsageFlagBits; typedef VkFlags VkImageUsageFlags; @@ -1611,6 +2016,7 @@ typedef enum VkMemoryPropertyFlagBits { VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020, VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0x00000040, VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0x00000080, + VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV = 0x00000100, VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkMemoryPropertyFlagBits; typedef VkFlags VkMemoryPropertyFlags; @@ -1621,6 +2027,12 @@ typedef enum VkQueueFlagBits { VK_QUEUE_TRANSFER_BIT = 0x00000004, VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, VK_QUEUE_PROTECTED_BIT = 0x00000010, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUEUE_VIDEO_DECODE_BIT_KHR = 0x00000020, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUEUE_VIDEO_ENCODE_BIT_KHR = 0x00000040, +#endif VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueueFlagBits; typedef VkFlags VkQueueFlags; @@ -1652,13 +2064,15 @@ typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000, - VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000, - VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000, + VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000, VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000, + VK_PIPELINE_STAGE_NONE_KHR = 0, + VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -1686,6 +2100,11 @@ typedef enum VkFenceCreateFlagBits { } VkFenceCreateFlagBits; typedef VkFlags VkFenceCreateFlags; typedef VkFlags VkSemaphoreCreateFlags; + +typedef enum VkEventCreateFlagBits { + VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = 0x00000001, + VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkEventCreateFlagBits; typedef VkFlags VkEventCreateFlags; typedef enum VkQueryPipelineStatisticFlagBits { @@ -1710,6 +2129,9 @@ typedef enum VkQueryResultFlagBits { VK_QUERY_RESULT_WAIT_BIT = 0x00000002, VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004, VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_RESULT_WITH_STATUS_BIT_KHR = 0x00000010, +#endif VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryResultFlagBits; typedef VkFlags VkQueryResultFlags; @@ -1737,11 +2159,25 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 0x00020000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00004000, +#endif VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, - VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR = 0x00000400, - VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000, + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000, +#endif + VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -1755,10 +2191,6 @@ typedef enum VkImageViewCreateFlagBits { VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageViewCreateFlagBits; typedef VkFlags VkImageViewCreateFlags; - -typedef enum VkShaderModuleCreateFlagBits { - VK_SHADER_MODULE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkShaderModuleCreateFlagBits; typedef VkFlags VkShaderModuleCreateFlags; typedef enum VkPipelineCacheCreateFlagBits { @@ -1782,12 +2214,15 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000, VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000, VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000, + VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0x00080000, VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020, VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0x00000040, VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080, @@ -1795,6 +2230,7 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0x00000800, VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = 0x00000100, VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = 0x00000200, + VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000, VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, @@ -1826,6 +2262,7 @@ typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040, VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080, + VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0x00004000, VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, @@ -1865,6 +2302,7 @@ typedef VkFlags VkSamplerCreateFlags; typedef enum VkDescriptorPoolCreateFlagBits { VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002, + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = 0x00000004, VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorPoolCreateFlagBits; @@ -1874,6 +2312,7 @@ typedef VkFlags VkDescriptorPoolResetFlags; typedef enum VkDescriptorSetLayoutCreateFlagBits { VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = 0x00000004, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorSetLayoutCreateFlagBits; @@ -2057,6 +2496,14 @@ typedef struct VkMemoryBarrier { VkAccessFlags dstAccessMask; } VkMemoryBarrier; +typedef struct VkPipelineCacheHeaderVersionOne { + uint32_t headerSize; + VkPipelineCacheHeaderVersion headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; +} VkPipelineCacheHeaderVersionOne; + typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( void* pUserData, size_t size, @@ -4014,13 +4461,13 @@ VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( #define VK_VERSION_1_1 1 // Vulkan 1.1 version number -#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)// Patch version should always be set to 0 +#define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)// Patch version should always be set to 0 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate) -#define VK_MAX_DEVICE_GROUP_SIZE 32 -#define VK_LUID_SIZE 8 -#define VK_QUEUE_FAMILY_EXTERNAL (~0U-1) +#define VK_MAX_DEVICE_GROUP_SIZE 32U +#define VK_LUID_SIZE 8U +#define VK_QUEUE_FAMILY_EXTERNAL (~1U) typedef enum VkPointClippingBehavior { VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0, @@ -4127,6 +4574,8 @@ typedef enum VkExternalMemoryHandleTypeFlagBits { VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0x00000400, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0x00000080, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0x00000800, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0x00001000, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, @@ -4191,6 +4640,7 @@ typedef enum VkExternalSemaphoreHandleTypeFlagBits { VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA = 0x00000080, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT, @@ -4876,10 +5326,10 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( #define VK_VERSION_1_2 1 // Vulkan 1.2 version number -#define VK_API_VERSION_1_2 VK_MAKE_VERSION(1, 2, 0)// Patch version should always be set to 0 +#define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)// Patch version should always be set to 0 -#define VK_MAX_DRIVER_NAME_SIZE 256 -#define VK_MAX_DRIVER_INFO_SIZE 256 +#define VK_MAX_DRIVER_NAME_SIZE 256U +#define VK_MAX_DRIVER_INFO_SIZE 256U typedef enum VkDriverId { VK_DRIVER_ID_AMD_PROPRIETARY = 1, @@ -4896,6 +5346,12 @@ typedef enum VkDriverId { VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12, VK_DRIVER_ID_MESA_LLVMPIPE = 13, VK_DRIVER_ID_MOLTENVK = 14, + VK_DRIVER_ID_COREAVI_PROPRIETARY = 15, + VK_DRIVER_ID_JUICE_PROPRIETARY = 16, + VK_DRIVER_ID_VERISILICON_PROPRIETARY = 17, + VK_DRIVER_ID_MESA_TURNIP = 18, + VK_DRIVER_ID_MESA_V3DV = 19, + VK_DRIVER_ID_MESA_PANVK = 20, VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, @@ -5809,7 +6265,7 @@ typedef struct VkAcquireNextImageInfoKHR { typedef struct VkDeviceGroupPresentCapabilitiesKHR { VkStructureType sType; - const void* pNext; + void* pNext; uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE]; VkDeviceGroupPresentModeFlagsKHR modes; } VkDeviceGroupPresentCapabilitiesKHR; @@ -6043,6 +6499,116 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" +#define VK_KHR_dynamic_rendering 1 +#define VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION 1 +#define VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME "VK_KHR_dynamic_rendering" + +typedef enum VkRenderingFlagBitsKHR { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = 0x00000001, + VK_RENDERING_SUSPENDING_BIT_KHR = 0x00000002, + VK_RENDERING_RESUMING_BIT_KHR = 0x00000004, + VK_RENDERING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRenderingFlagBitsKHR; +typedef VkFlags VkRenderingFlagsKHR; +typedef struct VkRenderingAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkResolveModeFlagBits resolveMode; + VkImageView resolveImageView; + VkImageLayout resolveImageLayout; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkClearValue clearValue; +} VkRenderingAttachmentInfoKHR; + +typedef struct VkRenderingInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingFlagsKHR flags; + VkRect2D renderArea; + uint32_t layerCount; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkRenderingAttachmentInfoKHR* pColorAttachments; + const VkRenderingAttachmentInfoKHR* pDepthAttachment; + const VkRenderingAttachmentInfoKHR* pStencilAttachment; +} VkRenderingInfoKHR; + +typedef struct VkPipelineRenderingCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkPipelineRenderingCreateInfoKHR; + +typedef struct VkPhysicalDeviceDynamicRenderingFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRendering; +} VkPhysicalDeviceDynamicRenderingFeaturesKHR; + +typedef struct VkCommandBufferInheritanceRenderingInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingFlagsKHR flags; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; + VkSampleCountFlagBits rasterizationSamples; +} VkCommandBufferInheritanceRenderingInfoKHR; + +typedef struct VkRenderingFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkExtent2D shadingRateAttachmentTexelSize; +} VkRenderingFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkRenderingFragmentDensityMapAttachmentInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; +} VkRenderingFragmentDensityMapAttachmentInfoEXT; + +typedef struct VkAttachmentSampleCountInfoAMD { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const VkSampleCountFlagBits* pColorAttachmentSamples; + VkSampleCountFlagBits depthStencilAttachmentSamples; +} VkAttachmentSampleCountInfoAMD; + +typedef VkAttachmentSampleCountInfoAMD VkAttachmentSampleCountInfoNV; + +typedef struct VkMultiviewPerViewAttributesInfoNVX { + VkStructureType sType; + const void* pNext; + VkBool32 perViewAttributes; + VkBool32 perViewAttributesPositionXOnly; +} VkMultiviewPerViewAttributesInfoNVX; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderingKHR)(VkCommandBuffer commandBuffer, const VkRenderingInfoKHR* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderingKHR)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderingKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInfoKHR* pRenderingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( + VkCommandBuffer commandBuffer); +#endif + + #define VK_KHR_multiview 1 #define VK_KHR_MULTIVIEW_SPEC_VERSION 1 #define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" @@ -6177,8 +6743,10 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( #define VK_KHR_maintenance1 1 -#define VK_KHR_MAINTENANCE1_SPEC_VERSION 2 -#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1" +#define VK_KHR_MAINTENANCE_1_SPEC_VERSION 2 +#define VK_KHR_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_maintenance1" +#define VK_KHR_MAINTENANCE1_SPEC_VERSION VK_KHR_MAINTENANCE_1_SPEC_VERSION +#define VK_KHR_MAINTENANCE1_EXTENSION_NAME VK_KHR_MAINTENANCE_1_EXTENSION_NAME typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR; typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); @@ -6412,7 +6980,7 @@ typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeature #define VK_KHR_incremental_present 1 -#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1 +#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 2 #define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" typedef struct VkRectLayerKHR { VkOffset2D offset; @@ -6657,8 +7225,10 @@ typedef enum VkPerformanceCounterStorageKHR { } VkPerformanceCounterStorageKHR; typedef enum VkPerformanceCounterDescriptionFlagBitsKHR { - VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = 0x00000001, - VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = 0x00000002, + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0x00000001, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0x00000002, + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR, VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkPerformanceCounterDescriptionFlagBitsKHR; typedef VkFlags VkPerformanceCounterDescriptionFlagsKHR; @@ -6682,7 +7252,7 @@ typedef struct VkPhysicalDevicePerformanceQueryPropertiesKHR { typedef struct VkPerformanceCounterKHR { VkStructureType sType; - const void* pNext; + void* pNext; VkPerformanceCounterUnitKHR unit; VkPerformanceCounterScopeKHR scope; VkPerformanceCounterStorageKHR storage; @@ -6691,7 +7261,7 @@ typedef struct VkPerformanceCounterKHR { typedef struct VkPerformanceCounterDescriptionKHR { VkStructureType sType; - const void* pNext; + void* pNext; VkPerformanceCounterDescriptionFlagsKHR flags; char name[VK_MAX_DESCRIPTION_SIZE]; char category[VK_MAX_DESCRIPTION_SIZE]; @@ -6756,8 +7326,10 @@ VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR( #define VK_KHR_maintenance2 1 -#define VK_KHR_MAINTENANCE2_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2" +#define VK_KHR_MAINTENANCE_2_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_2_EXTENSION_NAME "VK_KHR_maintenance2" +#define VK_KHR_MAINTENANCE2_SPEC_VERSION VK_KHR_MAINTENANCE_2_SPEC_VERSION +#define VK_KHR_MAINTENANCE2_EXTENSION_NAME VK_KHR_MAINTENANCE_2_EXTENSION_NAME typedef VkPointClippingBehavior VkPointClippingBehaviorKHR; typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR; @@ -7010,8 +7582,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( #define VK_KHR_maintenance3 1 -#define VK_KHR_MAINTENANCE3_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3" +#define VK_KHR_MAINTENANCE_3_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_3_EXTENSION_NAME "VK_KHR_maintenance3" +#define VK_KHR_MAINTENANCE3_SPEC_VERSION VK_KHR_MAINTENANCE_3_SPEC_VERSION +#define VK_KHR_MAINTENANCE3_EXTENSION_NAME VK_KHR_MAINTENANCE_3_EXTENSION_NAME typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR; typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR; @@ -7175,6 +7749,96 @@ typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryMo +#define VK_KHR_shader_terminate_invocation 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME "VK_KHR_shader_terminate_invocation" +typedef struct VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderTerminateInvocation; +} VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR; + + + +#define VK_KHR_fragment_shading_rate 1 +#define VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION 2 +#define VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME "VK_KHR_fragment_shading_rate" + +typedef enum VkFragmentShadingRateCombinerOpKHR { + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_ENUM_KHR = 0x7FFFFFFF +} VkFragmentShadingRateCombinerOpKHR; +typedef struct VkFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + const VkAttachmentReference2* pFragmentShadingRateAttachment; + VkExtent2D shadingRateAttachmentTexelSize; +} VkFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkExtent2D fragmentSize; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateStateCreateInfoKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineFragmentShadingRate; + VkBool32 primitiveFragmentShadingRate; + VkBool32 attachmentFragmentShadingRate; +} VkPhysicalDeviceFragmentShadingRateFeaturesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRatePropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentShadingRateAttachmentTexelSize; + VkExtent2D maxFragmentShadingRateAttachmentTexelSize; + uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio; + VkBool32 primitiveFragmentShadingRateWithMultipleViewports; + VkBool32 layeredShadingRateAttachments; + VkBool32 fragmentShadingRateNonTrivialCombinerOps; + VkExtent2D maxFragmentSize; + uint32_t maxFragmentSizeAspectRatio; + uint32_t maxFragmentShadingRateCoverageSamples; + VkSampleCountFlagBits maxFragmentShadingRateRasterizationSamples; + VkBool32 fragmentShadingRateWithShaderDepthStencilWrites; + VkBool32 fragmentShadingRateWithSampleMask; + VkBool32 fragmentShadingRateWithShaderSampleMask; + VkBool32 fragmentShadingRateWithConservativeRasterization; + VkBool32 fragmentShadingRateWithFragmentShaderInterlock; + VkBool32 fragmentShadingRateWithCustomSampleLocations; + VkBool32 fragmentShadingRateStrictMultiplyCombiner; +} VkPhysicalDeviceFragmentShadingRatePropertiesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateKHR { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleCounts; + VkExtent2D fragmentSize; +} VkPhysicalDeviceFragmentShadingRateKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pFragmentShadingRateCount, VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateKHR)(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceFragmentShadingRatesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pFragmentShadingRateCount, + VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( + VkCommandBuffer commandBuffer, + const VkExtent2D* pFragmentSize, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif + + #define VK_KHR_spirv_1_4 1 #define VK_KHR_SPIRV_1_4_SPEC_VERSION 1 #define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4" @@ -7202,6 +7866,26 @@ typedef VkAttachmentDescriptionStencilLayout VkAttachmentDescriptionStencilLayou +#define VK_KHR_present_wait 1 +#define VK_KHR_PRESENT_WAIT_SPEC_VERSION 1 +#define VK_KHR_PRESENT_WAIT_EXTENSION_NAME "VK_KHR_present_wait" +typedef struct VkPhysicalDevicePresentWaitFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait; +} VkPhysicalDevicePresentWaitFeaturesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresentKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresentKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t presentId, + uint64_t timeout); +#endif + + #define VK_KHR_uniform_buffer_standard_layout 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" @@ -7241,6 +7925,41 @@ VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( #endif +#define VK_KHR_deferred_host_operations 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) +#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 4 +#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" +typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); +typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); +typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( + VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkDeferredOperationKHR* pDeferredOperation); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( + VkDevice device, + VkDeferredOperationKHR operation, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif + + #define VK_KHR_pipeline_executable_properties 1 #define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1 #define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties" @@ -7331,14 +8050,652 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR #endif +#define VK_KHR_shader_integer_dot_product 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME "VK_KHR_shader_integer_dot_product" +typedef struct VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerDotProduct; +} VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; +} VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR; + + + +#define VK_KHR_pipeline_library 1 +#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" +typedef struct VkPipelineLibraryCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t libraryCount; + const VkPipeline* pLibraries; +} VkPipelineLibraryCreateInfoKHR; + + + #define VK_KHR_shader_non_semantic_info 1 #define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 #define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" +#define VK_KHR_present_id 1 +#define VK_KHR_PRESENT_ID_SPEC_VERSION 1 +#define VK_KHR_PRESENT_ID_EXTENSION_NAME "VK_KHR_present_id" +typedef struct VkPresentIdKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint64_t* pPresentIds; +} VkPresentIdKHR; + +typedef struct VkPhysicalDevicePresentIdFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId; +} VkPhysicalDevicePresentIdFeaturesKHR; + + + +#define VK_KHR_synchronization2 1 +typedef uint64_t VkFlags64; +#define VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION 1 +#define VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME "VK_KHR_synchronization2" +typedef VkFlags64 VkPipelineStageFlags2KHR; + +// Flag bits for VkPipelineStageFlagBits2KHR +typedef VkFlags64 VkPipelineStageFlagBits2KHR; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_NONE_KHR = 0ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0x04000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0x08000000ULL; +#endif +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; + +typedef VkFlags64 VkAccessFlags2KHR; + +// Flag bits for VkAccessFlagBits2KHR +typedef VkFlags64 VkAccessFlagBits2KHR; +static const VkAccessFlagBits2KHR VK_ACCESS_2_NONE_KHR = 0ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL; +#endif +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0x8000000000ULL; + + +typedef enum VkSubmitFlagBitsKHR { + VK_SUBMIT_PROTECTED_BIT_KHR = 0x00000001, + VK_SUBMIT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSubmitFlagBitsKHR; +typedef VkFlags VkSubmitFlagsKHR; +typedef struct VkMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; +} VkMemoryBarrier2KHR; + +typedef struct VkBufferMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier2KHR; + +typedef struct VkImageMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier2KHR; + +typedef struct VkDependencyInfoKHR { + VkStructureType sType; + const void* pNext; + VkDependencyFlags dependencyFlags; + uint32_t memoryBarrierCount; + const VkMemoryBarrier2KHR* pMemoryBarriers; + uint32_t bufferMemoryBarrierCount; + const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers; + uint32_t imageMemoryBarrierCount; + const VkImageMemoryBarrier2KHR* pImageMemoryBarriers; +} VkDependencyInfoKHR; + +typedef struct VkSemaphoreSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; + VkPipelineStageFlags2KHR stageMask; + uint32_t deviceIndex; +} VkSemaphoreSubmitInfoKHR; + +typedef struct VkCommandBufferSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + VkCommandBuffer commandBuffer; + uint32_t deviceMask; +} VkCommandBufferSubmitInfoKHR; + +typedef struct VkSubmitInfo2KHR { + VkStructureType sType; + const void* pNext; + VkSubmitFlagsKHR flags; + uint32_t waitSemaphoreInfoCount; + const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos; + uint32_t commandBufferInfoCount; + const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos; + uint32_t signalSemaphoreInfoCount; + const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos; +} VkSubmitInfo2KHR; + +typedef struct VkPhysicalDeviceSynchronization2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 synchronization2; +} VkPhysicalDeviceSynchronization2FeaturesKHR; + +typedef struct VkQueueFamilyCheckpointProperties2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2KHR checkpointExecutionStageMask; +} VkQueueFamilyCheckpointProperties2NV; + +typedef struct VkCheckpointData2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2KHR stage; + void* pCheckpointMarker; +} VkCheckpointData2NV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfoKHR* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2KHR stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2KHR)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfoKHR* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2KHR)(VkCommandBuffer commandBuffer, const VkDependencyInfoKHR* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2KHR)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR* pSubmits, VkFence fence); +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarker2AMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR stage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointData2NV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfoKHR* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2KHR stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2KHR( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfoKHR* pDependencyInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2KHR( + VkCommandBuffer commandBuffer, + const VkDependencyInfoKHR* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2KHR( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2KHR stage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2KHR( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2KHR* pSubmits, + VkFence fence); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2KHR stage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); + +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointData2NV* pCheckpointData); +#endif + + +#define VK_KHR_shader_subgroup_uniform_control_flow 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME "VK_KHR_shader_subgroup_uniform_control_flow" +typedef struct VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupUniformControlFlow; +} VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR; + + + +#define VK_KHR_zero_initialize_workgroup_memory 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME "VK_KHR_zero_initialize_workgroup_memory" +typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderZeroInitializeWorkgroupMemory; +} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR; + + + +#define VK_KHR_workgroup_memory_explicit_layout 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME "VK_KHR_workgroup_memory_explicit_layout" +typedef struct VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 workgroupMemoryExplicitLayout; + VkBool32 workgroupMemoryExplicitLayoutScalarBlockLayout; + VkBool32 workgroupMemoryExplicitLayout8BitAccess; + VkBool32 workgroupMemoryExplicitLayout16BitAccess; +} VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR; + + + +#define VK_KHR_copy_commands2 1 +#define VK_KHR_COPY_COMMANDS_2_SPEC_VERSION 1 +#define VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME "VK_KHR_copy_commands2" +typedef struct VkBufferCopy2KHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy2KHR; + +typedef struct VkCopyBufferInfo2KHR { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferCopy2KHR* pRegions; +} VkCopyBufferInfo2KHR; + +typedef struct VkImageCopy2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy2KHR; + +typedef struct VkCopyImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2KHR* pRegions; +} VkCopyImageInfo2KHR; + +typedef struct VkBufferImageCopy2KHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy2KHR; + +typedef struct VkCopyBufferToImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkBufferImageCopy2KHR* pRegions; +} VkCopyBufferToImageInfo2KHR; + +typedef struct VkCopyImageToBufferInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferImageCopy2KHR* pRegions; +} VkCopyImageToBufferInfo2KHR; + +typedef struct VkImageBlit2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit2KHR; + +typedef struct VkBlitImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageBlit2KHR* pRegions; + VkFilter filter; +} VkBlitImageInfo2KHR; + +typedef struct VkImageResolve2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve2KHR; + +typedef struct VkResolveImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageResolve2KHR* pRegions; +} VkResolveImageInfo2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2KHR* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2KHR* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2KHR)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2KHR* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2KHR)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2KHR* pResolveImageInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2KHR* pCopyBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2KHR* pCopyImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2KHR( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2KHR* pBlitImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2KHR* pResolveImageInfo); +#endif + + +#define VK_KHR_format_feature_flags2 1 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION 1 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME "VK_KHR_format_feature_flags2" +typedef VkFlags64 VkFormatFeatureFlags2KHR; + +// Flag bits for VkFormatFeatureFlagBits2KHR +typedef VkFlags64 VkFormatFeatureFlagBits2KHR; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR = 0x00000001ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR = 0x00000002ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR = 0x00000004ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000010ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT_KHR = 0x00000020ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT_KHR = 0x00000040ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT_KHR = 0x00000080ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT_KHR = 0x00000100ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR = 0x00000200ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_BLIT_SRC_BIT_KHR = 0x00000400ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_BLIT_DST_BIT_KHR = 0x00000800ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT_KHR = 0x00001000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0x00002000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR = 0x00004000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR = 0x00008000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT_KHR = 0x00010000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 0x00020000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 0x00040000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 0x00080000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 0x00100000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 0x00200000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR = 0x00400000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR = 0x00800000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR = 0x80000000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR = 0x100000000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR = 0x200000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000ULL; +#endif +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000ULL; +#endif + +typedef struct VkFormatProperties3KHR { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags2KHR linearTilingFeatures; + VkFormatFeatureFlags2KHR optimalTilingFeatures; + VkFormatFeatureFlags2KHR bufferFeatures; +} VkFormatProperties3KHR; + + + +#define VK_KHR_maintenance4 1 +#define VK_KHR_MAINTENANCE_4_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_4_EXTENSION_NAME "VK_KHR_maintenance4" +typedef struct VkPhysicalDeviceMaintenance4FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance4; +} VkPhysicalDeviceMaintenance4FeaturesKHR; + +typedef struct VkPhysicalDeviceMaintenance4PropertiesKHR { + VkStructureType sType; + void* pNext; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceMaintenance4PropertiesKHR; + +typedef struct VkDeviceBufferMemoryRequirementsKHR { + VkStructureType sType; + const void* pNext; + const VkBufferCreateInfo* pCreateInfo; +} VkDeviceBufferMemoryRequirementsKHR; + +typedef struct VkDeviceImageMemoryRequirementsKHR { + VkStructureType sType; + const void* pNext; + const VkImageCreateInfo* pCreateInfo; + VkImageAspectFlagBits planeAspect; +} VkDeviceImageMemoryRequirementsKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirementsKHR)(VkDevice device, const VkDeviceBufferMemoryRequirementsKHR* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirementsKHR* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirementsKHR* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirementsKHR( + VkDevice device, + const VkDeviceBufferMemoryRequirementsKHR* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirementsKHR* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirementsKHR* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif + + #define VK_EXT_debug_report 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) -#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9 +#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" typedef enum VkDebugReportObjectTypeEXT { @@ -7376,12 +8733,15 @@ typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, - VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000165000, + VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT = 1000029000, + VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT = 1000029001, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT = 1000366000, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugReportObjectTypeEXT; @@ -7654,6 +9014,77 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( #endif +#define VK_NVX_binary_import 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuModuleNVX) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuFunctionNVX) +#define VK_NVX_BINARY_IMPORT_SPEC_VERSION 1 +#define VK_NVX_BINARY_IMPORT_EXTENSION_NAME "VK_NVX_binary_import" +typedef struct VkCuModuleCreateInfoNVX { + VkStructureType sType; + const void* pNext; + size_t dataSize; + const void* pData; +} VkCuModuleCreateInfoNVX; + +typedef struct VkCuFunctionCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuModuleNVX module; + const char* pName; +} VkCuFunctionCreateInfoNVX; + +typedef struct VkCuLaunchInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuFunctionNVX function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCuLaunchInfoNVX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuModuleNVX)(VkDevice device, const VkCuModuleCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuModuleNVX* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuFunctionNVX)(VkDevice device, const VkCuFunctionCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuFunctionNVX* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCuModuleNVX)(VkDevice device, VkCuModuleNVX module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCuFunctionNVX)(VkDevice device, VkCuFunctionNVX function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCuLaunchKernelNVX)(VkCommandBuffer commandBuffer, const VkCuLaunchInfoNVX* pLaunchInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuModuleNVX( + VkDevice device, + const VkCuModuleCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuModuleNVX* pModule); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuFunctionNVX( + VkDevice device, + const VkCuFunctionCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuFunctionNVX* pFunction); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCuModuleNVX( + VkDevice device, + VkCuModuleNVX module, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCuFunctionNVX( + VkDevice device, + VkCuFunctionNVX function, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdCuLaunchKernelNVX( + VkCommandBuffer commandBuffer, + const VkCuLaunchInfoNVX* pLaunchInfo); +#endif + + #define VK_NVX_image_view_handle 1 #define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 2 #define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" @@ -8004,7 +9435,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( #define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" typedef enum VkSurfaceCounterFlagBitsEXT { - VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001, + VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0x00000001, + VK_SURFACE_COUNTER_VBLANK_EXT = VK_SURFACE_COUNTER_VBLANK_BIT_EXT, VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkSurfaceCounterFlagBitsEXT; typedef VkFlags VkSurfaceCounterFlagsEXT; @@ -8165,8 +9597,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( #define VK_NV_viewport_array2 1 -#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1 -#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2" +#define VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME "VK_NV_viewport_array2" +#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION +#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME #define VK_NVX_multiview_per_view_attributes 1 @@ -8348,7 +9782,7 @@ VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( #define VK_EXT_queue_family_foreign 1 #define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1 #define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign" -#define VK_QUEUE_FAMILY_FOREIGN_EXT (~0U-2) +#define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U) #define VK_EXT_debug_utils 1 @@ -8736,7 +10170,7 @@ typedef struct VkPhysicalDeviceShaderSMBuiltinsFeaturesNV { #define VK_EXT_image_drm_format_modifier 1 -#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 1 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 2 #define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier" typedef struct VkDrmFormatModifierPropertiesEXT { uint64_t drmFormatModifier; @@ -8781,6 +10215,19 @@ typedef struct VkImageDrmFormatModifierPropertiesEXT { uint64_t drmFormatModifier; } VkImageDrmFormatModifierPropertiesEXT; +typedef struct VkDrmFormatModifierProperties2EXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags2KHR drmFormatModifierTilingFeatures; +} VkDrmFormatModifierProperties2EXT; + +typedef struct VkDrmFormatModifierPropertiesList2EXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierProperties2EXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesList2EXT; + typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties); #ifndef VK_NO_PROTOTYPES @@ -8971,9 +10418,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( #define VK_NV_ray_tracing 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) -typedef VkAccelerationStructureKHR VkAccelerationStructureNV; - +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) #define VK_NV_RAY_TRACING_SPEC_VERSION 3 #define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" #define VK_SHADER_UNUSED_KHR (~0U) @@ -8994,7 +10439,7 @@ typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV; typedef enum VkGeometryTypeKHR { VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0, VK_GEOMETRY_TYPE_AABBS_KHR = 1, - VK_GEOMETRY_TYPE_INSTANCES_KHR = 1000150000, + VK_GEOMETRY_TYPE_INSTANCES_KHR = 2, VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF @@ -9005,6 +10450,7 @@ typedef VkGeometryTypeKHR VkGeometryTypeNV; typedef enum VkAccelerationStructureTypeKHR { VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, + VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF @@ -9024,17 +10470,12 @@ typedef enum VkCopyAccelerationStructureModeKHR { typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV; -typedef enum VkAccelerationStructureMemoryRequirementsTypeKHR { - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR = 0, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR = 1, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR = 2, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkAccelerationStructureMemoryRequirementsTypeKHR; -typedef VkAccelerationStructureMemoryRequirementsTypeKHR VkAccelerationStructureMemoryRequirementsTypeNV; - +typedef enum VkAccelerationStructureMemoryRequirementsTypeNV { + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMemoryRequirementsTypeNV; typedef enum VkGeometryFlagBitsKHR { VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001, @@ -9051,9 +10492,10 @@ typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV; typedef enum VkGeometryInstanceFlagBitsKHR { VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001, - VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = 0x00000002, + VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0x00000002, VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR, VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, @@ -9072,6 +10514,7 @@ typedef enum VkBuildAccelerationStructureFlagBitsKHR { VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, + VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0x00000020, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, @@ -9163,26 +10606,22 @@ typedef struct VkAccelerationStructureCreateInfoNV { VkAccelerationStructureInfoNV info; } VkAccelerationStructureCreateInfoNV; -typedef struct VkBindAccelerationStructureMemoryInfoKHR { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureKHR accelerationStructure; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; - uint32_t deviceIndexCount; - const uint32_t* pDeviceIndices; -} VkBindAccelerationStructureMemoryInfoKHR; +typedef struct VkBindAccelerationStructureMemoryInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureNV accelerationStructure; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindAccelerationStructureMemoryInfoNV; -typedef VkBindAccelerationStructureMemoryInfoKHR VkBindAccelerationStructureMemoryInfoNV; - -typedef struct VkWriteDescriptorSetAccelerationStructureKHR { - VkStructureType sType; - const void* pNext; - uint32_t accelerationStructureCount; - const VkAccelerationStructureKHR* pAccelerationStructures; -} VkWriteDescriptorSetAccelerationStructureKHR; - -typedef VkWriteDescriptorSetAccelerationStructureKHR VkWriteDescriptorSetAccelerationStructureNV; +typedef struct VkWriteDescriptorSetAccelerationStructureNV { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureNV* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureNV; typedef struct VkAccelerationStructureMemoryRequirementsInfoNV { VkStructureType sType; @@ -9233,20 +10672,17 @@ typedef struct VkAccelerationStructureInstanceKHR { typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); -typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureKHR)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); -typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryKHR)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos); -typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos); -typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureKHR dst, VkAccelerationStructureKHR src, VkBuffer scratch, VkDeviceSize scratchOffset); -typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureKHR dst, VkAccelerationStructureKHR src, VkCopyAccelerationStructureModeKHR mode); +typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth); typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); -typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, size_t dataSize, void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); -typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader); #ifndef VK_NO_PROTOTYPES @@ -9256,14 +10692,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV( const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); -VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR( - VkDevice device, - VkAccelerationStructureKHR accelerationStructure, - const VkAllocationCallbacks* pAllocator); - VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV( VkDevice device, - VkAccelerationStructureKHR accelerationStructure, + VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( @@ -9271,15 +10702,10 @@ VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); -VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryKHR( - VkDevice device, - uint32_t bindInfoCount, - const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos); - VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV( VkDevice device, uint32_t bindInfoCount, - const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos); + const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( VkCommandBuffer commandBuffer, @@ -9287,15 +10713,15 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, - VkAccelerationStructureKHR dst, - VkAccelerationStructureKHR src, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( VkCommandBuffer commandBuffer, - VkAccelerationStructureKHR dst, - VkAccelerationStructureKHR src, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( @@ -9341,22 +10767,14 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV( VkDevice device, - VkAccelerationStructureKHR accelerationStructure, + VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); -VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( - VkCommandBuffer commandBuffer, - uint32_t accelerationStructureCount, - const VkAccelerationStructureKHR* pAccelerationStructures, - VkQueryType queryType, - VkQueryPool queryPool, - uint32_t firstQuery); - VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, - const VkAccelerationStructureKHR* pAccelerationStructures, + const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); @@ -9492,7 +10910,7 @@ typedef struct VkPipelineCompilerControlCreateInfoAMD { #define VK_EXT_calibrated_timestamps 1 -#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 1 +#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 2 #define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps" typedef enum VkTimeDomainEXT { @@ -9971,7 +11389,7 @@ VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD( #define VK_EXT_fragment_density_map 1 -#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 2 #define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map" typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT { VkStructureType sType; @@ -10005,8 +11423,10 @@ typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLay #define VK_GOOGLE_hlsl_functionality1 1 -#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 1 -#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME #define VK_GOOGLE_decorate_string 1 @@ -10069,6 +11489,18 @@ typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD { +#define VK_EXT_shader_image_atomic_int64 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME "VK_EXT_shader_image_atomic_int64" +typedef struct VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderImageInt64Atomics; + VkBool32 sparseImageInt64Atomics; +} VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT; + + + #define VK_EXT_memory_budget 1 #define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 #define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget" @@ -10182,7 +11614,7 @@ typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; #define VK_EXT_validation_features 1 -#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 3 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 5 #define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" typedef enum VkValidationFeatureEnableEXT { @@ -10190,6 +11622,7 @@ typedef enum VkValidationFeatureEnableEXT { VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4, VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationFeatureEnableEXT; @@ -10201,6 +11634,7 @@ typedef enum VkValidationFeatureDisableEXT { VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4, VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5, VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6, + VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT = 7, VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationFeatureDisableEXT; typedef struct VkValidationFeaturesEXT { @@ -10342,6 +11776,37 @@ typedef struct VkPhysicalDeviceYcbcrImageArraysFeaturesEXT { +#define VK_EXT_provoking_vertex 1 +#define VK_EXT_PROVOKING_VERTEX_SPEC_VERSION 1 +#define VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME "VK_EXT_provoking_vertex" + +typedef enum VkProvokingVertexModeEXT { + VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0, + VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1, + VK_PROVOKING_VERTEX_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkProvokingVertexModeEXT; +typedef struct VkPhysicalDeviceProvokingVertexFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexLast; + VkBool32 transformFeedbackPreservesProvokingVertex; +} VkPhysicalDeviceProvokingVertexFeaturesEXT; + +typedef struct VkPhysicalDeviceProvokingVertexPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexModePerPipeline; + VkBool32 transformFeedbackPreservesTriangleFanProvokingVertex; +} VkPhysicalDeviceProvokingVertexPropertiesEXT; + +typedef struct VkPipelineRasterizationProvokingVertexStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkProvokingVertexModeEXT provokingVertexMode; +} VkPipelineRasterizationProvokingVertexStateCreateInfoEXT; + + + #define VK_EXT_headless_surface 1 #define VK_EXT_HEADLESS_SURFACE_SPEC_VERSION 1 #define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" @@ -10543,6 +12008,28 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( #endif +#define VK_EXT_shader_atomic_float2 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME "VK_EXT_shader_atomic_float2" +typedef struct VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat16Atomics; + VkBool32 shaderBufferFloat16AtomicAdd; + VkBool32 shaderBufferFloat16AtomicMinMax; + VkBool32 shaderBufferFloat32AtomicMinMax; + VkBool32 shaderBufferFloat64AtomicMinMax; + VkBool32 shaderSharedFloat16Atomics; + VkBool32 shaderSharedFloat16AtomicAdd; + VkBool32 shaderSharedFloat16AtomicMinMax; + VkBool32 shaderSharedFloat32AtomicMinMax; + VkBool32 shaderSharedFloat64AtomicMinMax; + VkBool32 shaderImageFloat32AtomicMinMax; + VkBool32 sparseImageFloat32AtomicMinMax; +} VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT; + + + #define VK_EXT_shader_demote_to_helper_invocation 1 #define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1 #define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation" @@ -10744,6 +12231,25 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( #endif +#define VK_NV_inherited_viewport_scissor 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME "VK_NV_inherited_viewport_scissor" +typedef struct VkPhysicalDeviceInheritedViewportScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 inheritedViewportScissor2D; +} VkPhysicalDeviceInheritedViewportScissorFeaturesNV; + +typedef struct VkCommandBufferInheritanceViewportScissorInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportScissor2D; + uint32_t viewportDepthCount; + const VkViewport* pViewportDepths; +} VkCommandBufferInheritanceViewportScissorInfoNV; + + + #define VK_EXT_texel_buffer_alignment 1 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" @@ -10765,7 +12271,7 @@ typedef struct VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT { #define VK_QCOM_render_pass_transform 1 -#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 2 #define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" typedef struct VkRenderPassTransformBeginInfoQCOM { VkStructureType sType; @@ -10782,6 +12288,71 @@ typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { +#define VK_EXT_device_memory_report 1 +#define VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME "VK_EXT_device_memory_report" + +typedef enum VkDeviceMemoryReportEventTypeEXT { + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT = 0, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT = 1, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT = 2, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT = 3, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT = 4, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceMemoryReportEventTypeEXT; +typedef VkFlags VkDeviceMemoryReportFlagsEXT; +typedef struct VkPhysicalDeviceDeviceMemoryReportFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 deviceMemoryReport; +} VkPhysicalDeviceDeviceMemoryReportFeaturesEXT; + +typedef struct VkDeviceMemoryReportCallbackDataEXT { + VkStructureType sType; + void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + VkDeviceMemoryReportEventTypeEXT type; + uint64_t memoryObjectId; + VkDeviceSize size; + VkObjectType objectType; + uint64_t objectHandle; + uint32_t heapIndex; +} VkDeviceMemoryReportCallbackDataEXT; + +typedef void (VKAPI_PTR *PFN_vkDeviceMemoryReportCallbackEXT)( + const VkDeviceMemoryReportCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDeviceDeviceMemoryReportCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback; + void* pUserData; +} VkDeviceDeviceMemoryReportCreateInfoEXT; + + + +#define VK_EXT_acquire_drm_display 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_drm_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, uint32_t connectorId, VkDisplayKHR* display); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + uint32_t connectorId, + VkDisplayKHR* display); +#endif + + #define VK_EXT_robustness2 1 #define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 #define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" @@ -10929,8 +12500,166 @@ typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { #define VK_QCOM_render_pass_store_ops 1 -#define VK_QCOM_render_pass_store_ops_SPEC_VERSION 2 -#define VK_QCOM_render_pass_store_ops_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" +#define VK_QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION 2 +#define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" + + +#define VK_NV_fragment_shading_rate_enums 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME "VK_NV_fragment_shading_rate_enums" + +typedef enum VkFragmentShadingRateTypeNV { + VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0, + VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1, + VK_FRAGMENT_SHADING_RATE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateTypeNV; + +typedef enum VkFragmentShadingRateNV { + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10, + VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11, + VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12, + VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13, + VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14, + VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15, + VK_FRAGMENT_SHADING_RATE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateNV; +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShadingRateEnums; + VkBool32 supersampleFragmentShadingRates; + VkBool32 noInvocationFragmentShadingRates; +} VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV; + +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV { + VkStructureType sType; + void* pNext; + VkSampleCountFlagBits maxFragmentShadingRateInvocationCount; +} VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV; + +typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkFragmentShadingRateTypeNV shadingRateType; + VkFragmentShadingRateNV shadingRate; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateEnumStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateEnumNV)(VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( + VkCommandBuffer commandBuffer, + VkFragmentShadingRateNV shadingRate, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif + + +#define VK_NV_ray_tracing_motion_blur 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME "VK_NV_ray_tracing_motion_blur" + +typedef enum VkAccelerationStructureMotionInstanceTypeNV { + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV = 0, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV = 1, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV = 2, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMotionInstanceTypeNV; +typedef VkFlags VkAccelerationStructureMotionInfoFlagsNV; +typedef VkFlags VkAccelerationStructureMotionInstanceFlagsNV; +typedef union VkDeviceOrHostAddressConstKHR { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstKHR; + +typedef struct VkAccelerationStructureGeometryMotionTrianglesDataNV { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR vertexData; +} VkAccelerationStructureGeometryMotionTrianglesDataNV; + +typedef struct VkAccelerationStructureMotionInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t maxInstances; + VkAccelerationStructureMotionInfoFlagsNV flags; +} VkAccelerationStructureMotionInfoNV; + +typedef struct VkAccelerationStructureMatrixMotionInstanceNV { + VkTransformMatrixKHR transformT0; + VkTransformMatrixKHR transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureMatrixMotionInstanceNV; + +typedef struct VkSRTDataNV { + float sx; + float a; + float b; + float pvx; + float sy; + float c; + float pvy; + float sz; + float pvz; + float qx; + float qy; + float qz; + float qw; + float tx; + float ty; + float tz; +} VkSRTDataNV; + +typedef struct VkAccelerationStructureSRTMotionInstanceNV { + VkSRTDataNV transformT0; + VkSRTDataNV transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureSRTMotionInstanceNV; + +typedef union VkAccelerationStructureMotionInstanceDataNV { + VkAccelerationStructureInstanceKHR staticInstance; + VkAccelerationStructureMatrixMotionInstanceNV matrixMotionInstance; + VkAccelerationStructureSRTMotionInstanceNV srtMotionInstance; +} VkAccelerationStructureMotionInstanceDataNV; + +typedef struct VkAccelerationStructureMotionInstanceNV { + VkAccelerationStructureMotionInstanceTypeNV type; + VkAccelerationStructureMotionInstanceFlagsNV flags; + VkAccelerationStructureMotionInstanceDataNV data; +} VkAccelerationStructureMotionInstanceNV; + +typedef struct VkPhysicalDeviceRayTracingMotionBlurFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingMotionBlur; + VkBool32 rayTracingMotionBlurPipelineTraceRaysIndirect; +} VkPhysicalDeviceRayTracingMotionBlurFeaturesNV; + + + +#define VK_EXT_ycbcr_2plane_444_formats 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME "VK_EXT_ycbcr_2plane_444_formats" +typedef struct VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 ycbcr2plane444Formats; +} VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT; + #define VK_EXT_fragment_density_map2 1 @@ -10953,6 +12682,17 @@ typedef struct VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { +#define VK_QCOM_rotated_copy_commands 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME "VK_QCOM_rotated_copy_commands" +typedef struct VkCopyCommandTransformInfoQCOM { + VkStructureType sType; + const void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkCopyCommandTransformInfoQCOM; + + + #define VK_EXT_image_robustness 1 #define VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION 1 #define VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_image_robustness" @@ -10963,6 +12703,836 @@ typedef struct VkPhysicalDeviceImageRobustnessFeaturesEXT { } VkPhysicalDeviceImageRobustnessFeaturesEXT; + +#define VK_EXT_4444_formats 1 +#define VK_EXT_4444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_4444_FORMATS_EXTENSION_NAME "VK_EXT_4444_formats" +typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatA4R4G4B4; + VkBool32 formatA4B4G4R4; +} VkPhysicalDevice4444FormatsFeaturesEXT; + + + +#define VK_EXT_rgba10x6_formats 1 +#define VK_EXT_RGBA10X6_FORMATS_SPEC_VERSION 1 +#define VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME "VK_EXT_rgba10x6_formats" +typedef struct VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatRgba10x6WithoutYCbCrSampler; +} VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT; + + + +#define VK_NV_acquire_winrt_display 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME "VK_NV_acquire_winrt_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireWinrtDisplayNV)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetWinrtDisplayNV)(VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + uint32_t deviceRelativeId, + VkDisplayKHR* pDisplay); +#endif + + +#define VK_VALVE_mutable_descriptor_type 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_VALVE_mutable_descriptor_type" +typedef struct VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 mutableDescriptorType; +} VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE; + +typedef struct VkMutableDescriptorTypeListVALVE { + uint32_t descriptorTypeCount; + const VkDescriptorType* pDescriptorTypes; +} VkMutableDescriptorTypeListVALVE; + +typedef struct VkMutableDescriptorTypeCreateInfoVALVE { + VkStructureType sType; + const void* pNext; + uint32_t mutableDescriptorTypeListCount; + const VkMutableDescriptorTypeListVALVE* pMutableDescriptorTypeLists; +} VkMutableDescriptorTypeCreateInfoVALVE; + + + +#define VK_EXT_vertex_input_dynamic_state 1 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION 2 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_vertex_input_dynamic_state" +typedef struct VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexInputDynamicState; +} VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT; + +typedef struct VkVertexInputBindingDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; + uint32_t divisor; +} VkVertexInputBindingDescription2EXT; + +typedef struct VkVertexInputAttributeDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription2EXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetVertexInputEXT)(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( + VkCommandBuffer commandBuffer, + uint32_t vertexBindingDescriptionCount, + const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, + uint32_t vertexAttributeDescriptionCount, + const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); +#endif + + +#define VK_EXT_physical_device_drm 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME "VK_EXT_physical_device_drm" +typedef struct VkPhysicalDeviceDrmPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 hasPrimary; + VkBool32 hasRender; + int64_t primaryMajor; + int64_t primaryMinor; + int64_t renderMajor; + int64_t renderMinor; +} VkPhysicalDeviceDrmPropertiesEXT; + + + +#define VK_EXT_primitive_topology_list_restart 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME "VK_EXT_primitive_topology_list_restart" +typedef struct VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitiveTopologyListRestart; + VkBool32 primitiveTopologyPatchListRestart; +} VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT; + + + +#define VK_HUAWEI_subpass_shading 1 +#define VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION 2 +#define VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME "VK_HUAWEI_subpass_shading" +typedef struct VkSubpassShadingPipelineCreateInfoHUAWEI { + VkStructureType sType; + void* pNext; + VkRenderPass renderPass; + uint32_t subpass; +} VkSubpassShadingPipelineCreateInfoHUAWEI; + +typedef struct VkPhysicalDeviceSubpassShadingFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 subpassShading; +} VkPhysicalDeviceSubpassShadingFeaturesHUAWEI; + +typedef struct VkPhysicalDeviceSubpassShadingPropertiesHUAWEI { + VkStructureType sType; + void* pNext; + uint32_t maxSubpassShadingWorkgroupSizeAspectRatio; +} VkPhysicalDeviceSubpassShadingPropertiesHUAWEI; + +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)(VkDevice device, VkRenderPass renderpass, VkExtent2D* pMaxWorkgroupSize); +typedef void (VKAPI_PTR *PFN_vkCmdSubpassShadingHUAWEI)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI( + VkDevice device, + VkRenderPass renderpass, + VkExtent2D* pMaxWorkgroupSize); + +VKAPI_ATTR void VKAPI_CALL vkCmdSubpassShadingHUAWEI( + VkCommandBuffer commandBuffer); +#endif + + +#define VK_HUAWEI_invocation_mask 1 +#define VK_HUAWEI_INVOCATION_MASK_SPEC_VERSION 1 +#define VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME "VK_HUAWEI_invocation_mask" +typedef struct VkPhysicalDeviceInvocationMaskFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 invocationMask; +} VkPhysicalDeviceInvocationMaskFeaturesHUAWEI; + +typedef void (VKAPI_PTR *PFN_vkCmdBindInvocationMaskHUAWEI)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindInvocationMaskHUAWEI( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); +#endif + + +#define VK_NV_external_memory_rdma 1 +typedef void* VkRemoteAddressNV; +#define VK_NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME "VK_NV_external_memory_rdma" +typedef struct VkMemoryGetRemoteAddressInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetRemoteAddressInfoNV; + +typedef struct VkPhysicalDeviceExternalMemoryRDMAFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 externalMemoryRDMA; +} VkPhysicalDeviceExternalMemoryRDMAFeaturesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryRemoteAddressNV)(VkDevice device, const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, VkRemoteAddressNV* pAddress); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryRemoteAddressNV( + VkDevice device, + const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, + VkRemoteAddressNV* pAddress); +#endif + + +#define VK_EXT_extended_dynamic_state2 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME "VK_EXT_extended_dynamic_state2" +typedef struct VkPhysicalDeviceExtendedDynamicState2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState2; + VkBool32 extendedDynamicState2LogicOp; + VkBool32 extendedDynamicState2PatchControlPoints; +} VkPhysicalDeviceExtendedDynamicState2FeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetPatchControlPointsEXT)(VkCommandBuffer commandBuffer, uint32_t patchControlPoints); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEXT)(VkCommandBuffer commandBuffer, VkLogicOp logicOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPatchControlPointsEXT( + VkCommandBuffer commandBuffer, + uint32_t patchControlPoints); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEXT( + VkCommandBuffer commandBuffer, + VkLogicOp logicOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable); +#endif + + +#define VK_EXT_color_write_enable 1 +#define VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION 1 +#define VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME "VK_EXT_color_write_enable" +typedef struct VkPhysicalDeviceColorWriteEnableFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 colorWriteEnable; +} VkPhysicalDeviceColorWriteEnableFeaturesEXT; + +typedef struct VkPipelineColorWriteCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentCount; + const VkBool32* pColorWriteEnables; +} VkPipelineColorWriteCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteEnableEXT)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteEnableEXT( + VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkBool32* pColorWriteEnables); +#endif + + +#define VK_EXT_global_priority_query 1 +#define VK_MAX_GLOBAL_PRIORITY_SIZE_EXT 16U +#define VK_EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION 1 +#define VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME "VK_EXT_global_priority_query" +typedef struct VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 globalPriorityQuery; +} VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT; + +typedef struct VkQueueFamilyGlobalPriorityPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t priorityCount; + VkQueueGlobalPriorityEXT priorities[VK_MAX_GLOBAL_PRIORITY_SIZE_EXT]; +} VkQueueFamilyGlobalPriorityPropertiesEXT; + + + +#define VK_EXT_multi_draw 1 +#define VK_EXT_MULTI_DRAW_SPEC_VERSION 1 +#define VK_EXT_MULTI_DRAW_EXTENSION_NAME "VK_EXT_multi_draw" +typedef struct VkPhysicalDeviceMultiDrawFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 multiDraw; +} VkPhysicalDeviceMultiDrawFeaturesEXT; + +typedef struct VkPhysicalDeviceMultiDrawPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxMultiDrawCount; +} VkPhysicalDeviceMultiDrawPropertiesEXT; + +typedef struct VkMultiDrawInfoEXT { + uint32_t firstVertex; + uint32_t vertexCount; +} VkMultiDrawInfoEXT; + +typedef struct VkMultiDrawIndexedInfoEXT { + uint32_t firstIndex; + uint32_t indexCount; + int32_t vertexOffset; +} VkMultiDrawIndexedInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT* pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiIndexedEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawInfoEXT* pVertexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT* pIndexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride, + const int32_t* pVertexOffset); +#endif + + +#define VK_EXT_load_store_op_none 1 +#define VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION 1 +#define VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_EXT_load_store_op_none" + + +#define VK_EXT_border_color_swizzle 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME "VK_EXT_border_color_swizzle" +typedef struct VkPhysicalDeviceBorderColorSwizzleFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 borderColorSwizzle; + VkBool32 borderColorSwizzleFromImage; +} VkPhysicalDeviceBorderColorSwizzleFeaturesEXT; + +typedef struct VkSamplerBorderColorComponentMappingCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkComponentMapping components; + VkBool32 srgb; +} VkSamplerBorderColorComponentMappingCreateInfoEXT; + + + +#define VK_EXT_pageable_device_local_memory 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME "VK_EXT_pageable_device_local_memory" +typedef struct VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pageableDeviceLocalMemory; +} VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkSetDeviceMemoryPriorityEXT)(VkDevice device, VkDeviceMemory memory, float priority); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetDeviceMemoryPriorityEXT( + VkDevice device, + VkDeviceMemory memory, + float priority); +#endif + + +#define VK_KHR_acceleration_structure 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) +#define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 +#define VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_KHR_acceleration_structure" + +typedef enum VkBuildAccelerationStructureModeKHR { + VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR = 0, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureModeKHR; + +typedef enum VkAccelerationStructureBuildTypeKHR { + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureBuildTypeKHR; + +typedef enum VkAccelerationStructureCompatibilityKHR { + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCompatibilityKHR; + +typedef enum VkAccelerationStructureCreateFlagBitsKHR { + VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001, + VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0x00000004, + VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCreateFlagBitsKHR; +typedef VkFlags VkAccelerationStructureCreateFlagsKHR; +typedef union VkDeviceOrHostAddressKHR { + VkDeviceAddress deviceAddress; + void* hostAddress; +} VkDeviceOrHostAddressKHR; + +typedef struct VkAccelerationStructureBuildRangeInfoKHR { + uint32_t primitiveCount; + uint32_t primitiveOffset; + uint32_t firstVertex; + uint32_t transformOffset; +} VkAccelerationStructureBuildRangeInfoKHR; + +typedef struct VkAccelerationStructureGeometryTrianglesDataKHR { + VkStructureType sType; + const void* pNext; + VkFormat vertexFormat; + VkDeviceOrHostAddressConstKHR vertexData; + VkDeviceSize vertexStride; + uint32_t maxVertex; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexData; + VkDeviceOrHostAddressConstKHR transformData; +} VkAccelerationStructureGeometryTrianglesDataKHR; + +typedef struct VkAccelerationStructureGeometryAabbsDataKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR data; + VkDeviceSize stride; +} VkAccelerationStructureGeometryAabbsDataKHR; + +typedef struct VkAccelerationStructureGeometryInstancesDataKHR { + VkStructureType sType; + const void* pNext; + VkBool32 arrayOfPointers; + VkDeviceOrHostAddressConstKHR data; +} VkAccelerationStructureGeometryInstancesDataKHR; + +typedef union VkAccelerationStructureGeometryDataKHR { + VkAccelerationStructureGeometryTrianglesDataKHR triangles; + VkAccelerationStructureGeometryAabbsDataKHR aabbs; + VkAccelerationStructureGeometryInstancesDataKHR instances; +} VkAccelerationStructureGeometryDataKHR; + +typedef struct VkAccelerationStructureGeometryKHR { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkAccelerationStructureGeometryDataKHR geometry; + VkGeometryFlagsKHR flags; +} VkAccelerationStructureGeometryKHR; + +typedef struct VkAccelerationStructureBuildGeometryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeKHR type; + VkBuildAccelerationStructureFlagsKHR flags; + VkBuildAccelerationStructureModeKHR mode; + VkAccelerationStructureKHR srcAccelerationStructure; + VkAccelerationStructureKHR dstAccelerationStructure; + uint32_t geometryCount; + const VkAccelerationStructureGeometryKHR* pGeometries; + const VkAccelerationStructureGeometryKHR* const* ppGeometries; + VkDeviceOrHostAddressKHR scratchData; +} VkAccelerationStructureBuildGeometryInfoKHR; + +typedef struct VkAccelerationStructureCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureCreateFlagsKHR createFlags; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; + VkAccelerationStructureTypeKHR type; + VkDeviceAddress deviceAddress; +} VkAccelerationStructureCreateInfoKHR; + +typedef struct VkWriteDescriptorSetAccelerationStructureKHR { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureKHR* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureKHR; + +typedef struct VkPhysicalDeviceAccelerationStructureFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 accelerationStructure; + VkBool32 accelerationStructureCaptureReplay; + VkBool32 accelerationStructureIndirectBuild; + VkBool32 accelerationStructureHostCommands; + VkBool32 descriptorBindingAccelerationStructureUpdateAfterBind; +} VkPhysicalDeviceAccelerationStructureFeaturesKHR; + +typedef struct VkPhysicalDeviceAccelerationStructurePropertiesKHR { + VkStructureType sType; + void* pNext; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxPrimitiveCount; + uint32_t maxPerStageDescriptorAccelerationStructures; + uint32_t maxPerStageDescriptorUpdateAfterBindAccelerationStructures; + uint32_t maxDescriptorSetAccelerationStructures; + uint32_t maxDescriptorSetUpdateAfterBindAccelerationStructures; + uint32_t minAccelerationStructureScratchOffsetAlignment; +} VkPhysicalDeviceAccelerationStructurePropertiesKHR; + +typedef struct VkAccelerationStructureDeviceAddressInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; +} VkAccelerationStructureDeviceAddressInfoKHR; + +typedef struct VkAccelerationStructureVersionInfoKHR { + VkStructureType sType; + const void* pNext; + const uint8_t* pVersionData; +} VkAccelerationStructureVersionInfoKHR; + +typedef struct VkCopyAccelerationStructureToMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkDeviceOrHostAddressKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureToMemoryInfoKHR; + +typedef struct VkCopyMemoryToAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyMemoryToAccelerationStructureInfoKHR; + +typedef struct VkCopyAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureInfoKHR; + +typedef struct VkAccelerationStructureBuildSizesInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize accelerationStructureSize; + VkDeviceSize updateScratchSize; + VkDeviceSize buildScratchSize; +} VkAccelerationStructureBuildSizesInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureKHR)(VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureKHR)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresIndirectKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkDeviceAddress* pIndirectDeviceAddresses, const uint32_t* pIndirectStrides, const uint32_t* const* ppMaxPrimitiveCounts); +typedef VkResult (VKAPI_PTR *PFN_vkBuildAccelerationStructuresKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureToMemoryKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteAccelerationStructuresPropertiesKHR)(VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetAccelerationStructureDeviceAddressKHR)(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(VkDevice device, const VkAccelerationStructureVersionInfoKHR* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureBuildSizesKHR)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR( + VkDevice device, + const VkAccelerationStructureCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureKHR* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR( + VkDevice device, + VkAccelerationStructureKHR accelerationStructure, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresIndirectKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkDeviceAddress* pIndirectDeviceAddresses, + const uint32_t* pIndirectStrides, + const uint32_t* const* ppMaxPrimitiveCounts); + +VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructuresKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( + VkDevice device, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + size_t dataSize, + void* pData, + size_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR( + VkDevice device, + const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR( + VkDevice device, + const VkAccelerationStructureVersionInfoKHR* pVersionInfo, + VkAccelerationStructureCompatibilityKHR* pCompatibility); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( + VkDevice device, + VkAccelerationStructureBuildTypeKHR buildType, + const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, + const uint32_t* pMaxPrimitiveCounts, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif + + +#define VK_KHR_ray_tracing_pipeline 1 +#define VK_KHR_RAY_TRACING_PIPELINE_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME "VK_KHR_ray_tracing_pipeline" + +typedef enum VkShaderGroupShaderKHR { + VK_SHADER_GROUP_SHADER_GENERAL_KHR = 0, + VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR = 1, + VK_SHADER_GROUP_SHADER_ANY_HIT_KHR = 2, + VK_SHADER_GROUP_SHADER_INTERSECTION_KHR = 3, + VK_SHADER_GROUP_SHADER_MAX_ENUM_KHR = 0x7FFFFFFF +} VkShaderGroupShaderKHR; +typedef struct VkRayTracingShaderGroupCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; + const void* pShaderGroupCaptureReplayHandle; +} VkRayTracingShaderGroupCreateInfoKHR; + +typedef struct VkRayTracingPipelineInterfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxPipelineRayPayloadSize; + uint32_t maxPipelineRayHitAttributeSize; +} VkRayTracingPipelineInterfaceCreateInfoKHR; + +typedef struct VkRayTracingPipelineCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoKHR* pGroups; + uint32_t maxPipelineRayRecursionDepth; + const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; + const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelineFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingPipeline; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplay; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplayMixed; + VkBool32 rayTracingPipelineTraceRaysIndirect; + VkBool32 rayTraversalPrimitiveCulling; +} VkPhysicalDeviceRayTracingPipelineFeaturesKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelinePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRayRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint32_t shaderGroupHandleCaptureReplaySize; + uint32_t maxRayDispatchInvocationCount; + uint32_t shaderGroupHandleAlignment; + uint32_t maxRayHitAttributeSize; +} VkPhysicalDeviceRayTracingPipelinePropertiesKHR; + +typedef struct VkStridedDeviceAddressRegionKHR { + VkDeviceAddress deviceAddress; + VkDeviceSize stride; + VkDeviceSize size; +} VkStridedDeviceAddressRegionKHR; + +typedef struct VkTraceRaysIndirectCommandKHR { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommandKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirectKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, VkDeviceAddress indirectDeviceAddress); +typedef VkDeviceSize (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupStackSizeKHR)(VkDevice device, VkPipeline pipeline, uint32_t group, VkShaderGroupShaderKHR groupShader); +typedef void (VKAPI_PTR *PFN_vkCmdSetRayTracingPipelineStackSizeKHR)(VkCommandBuffer commandBuffer, uint32_t pipelineStackSize); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + uint32_t width, + uint32_t height, + uint32_t depth); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + VkDeviceAddress indirectDeviceAddress); + +VKAPI_ATTR VkDeviceSize VKAPI_CALL vkGetRayTracingShaderGroupStackSizeKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t group, + VkShaderGroupShaderKHR groupShader); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRayTracingPipelineStackSizeKHR( + VkCommandBuffer commandBuffer, + uint32_t pipelineStackSize); +#endif + + +#define VK_KHR_ray_query 1 +#define VK_KHR_RAY_QUERY_SPEC_VERSION 1 +#define VK_KHR_RAY_QUERY_EXTENSION_NAME "VK_KHR_ray_query" +typedef struct VkPhysicalDeviceRayQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayQuery; +} VkPhysicalDeviceRayQueryFeaturesKHR; + + #ifdef __cplusplus } #endif diff --git a/third_party/vulkan/vulkan_directfb.h b/third_party/vulkan/vulkan_directfb.h index f75bd3a4e..8eaac6e48 100644 --- a/third_party/vulkan/vulkan_directfb.h +++ b/third_party/vulkan/vulkan_directfb.h @@ -2,7 +2,7 @@ #define VULKAN_DIRECTFB_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/third_party/vulkan/vulkan_fuchsia.h b/third_party/vulkan/vulkan_fuchsia.h index 03e27cb0a..44b4ace3e 100644 --- a/third_party/vulkan/vulkan_fuchsia.h +++ b/third_party/vulkan/vulkan_fuchsia.h @@ -2,7 +2,7 @@ #define VULKAN_FUCHSIA_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -40,6 +40,217 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA( VkSurfaceKHR* pSurface); #endif + +#define VK_FUCHSIA_external_memory 1 +#define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory" +typedef struct VkImportMemoryZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + zx_handle_t handle; +} VkImportMemoryZirconHandleInfoFUCHSIA; + +typedef struct VkMemoryZirconHandlePropertiesFUCHSIA { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryZirconHandlePropertiesFUCHSIA; + +typedef struct VkMemoryGetZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetZirconHandleInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryZirconHandleFUCHSIA)(VkDevice device, const VkMemoryGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, zx_handle_t* pZirconHandle); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, zx_handle_t zirconHandle, VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandleFUCHSIA( + VkDevice device, + const VkMemoryGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, + zx_handle_t* pZirconHandle); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandlePropertiesFUCHSIA( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + zx_handle_t zirconHandle, + VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties); +#endif + + +#define VK_FUCHSIA_external_semaphore 1 +#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 +#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_FUCHSIA_external_semaphore" +typedef struct VkImportSemaphoreZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + zx_handle_t zirconHandle; +} VkImportSemaphoreZirconHandleInfoFUCHSIA; + +typedef struct VkSemaphoreGetZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetZirconHandleInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreZirconHandleFUCHSIA)(VkDevice device, const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreZirconHandleFUCHSIA)(VkDevice device, const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, zx_handle_t* pZirconHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreZirconHandleFUCHSIA( + VkDevice device, + const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreZirconHandleFUCHSIA( + VkDevice device, + const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, + zx_handle_t* pZirconHandle); +#endif + + +#define VK_FUCHSIA_buffer_collection 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA) +#define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 2 +#define VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME "VK_FUCHSIA_buffer_collection" +typedef VkFlags VkImageFormatConstraintsFlagsFUCHSIA; + +typedef enum VkImageConstraintsInfoFlagBitsFUCHSIA { + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA = 0x00000001, + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA = 0x00000002, + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA = 0x00000004, + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA = 0x00000008, + VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA = 0x00000010, + VK_IMAGE_CONSTRAINTS_INFO_FLAG_BITS_MAX_ENUM_FUCHSIA = 0x7FFFFFFF +} VkImageConstraintsInfoFlagBitsFUCHSIA; +typedef VkFlags VkImageConstraintsInfoFlagsFUCHSIA; +typedef struct VkBufferCollectionCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + zx_handle_t collectionToken; +} VkBufferCollectionCreateInfoFUCHSIA; + +typedef struct VkImportMemoryBufferCollectionFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkImportMemoryBufferCollectionFUCHSIA; + +typedef struct VkBufferCollectionImageCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionImageCreateInfoFUCHSIA; + +typedef struct VkBufferCollectionConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t minBufferCount; + uint32_t maxBufferCount; + uint32_t minBufferCountForCamping; + uint32_t minBufferCountForDedicatedSlack; + uint32_t minBufferCountForSharedSlack; +} VkBufferCollectionConstraintsInfoFUCHSIA; + +typedef struct VkBufferConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCreateInfo createInfo; + VkFormatFeatureFlags requiredFormatFeatures; + VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints; +} VkBufferConstraintsInfoFUCHSIA; + +typedef struct VkBufferCollectionBufferCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionBufferCreateInfoFUCHSIA; + +typedef struct VkSysmemColorSpaceFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t colorSpace; +} VkSysmemColorSpaceFUCHSIA; + +typedef struct VkBufferCollectionPropertiesFUCHSIA { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; + uint32_t bufferCount; + uint32_t createInfoIndex; + uint64_t sysmemPixelFormat; + VkFormatFeatureFlags formatFeatures; + VkSysmemColorSpaceFUCHSIA sysmemColorSpaceIndex; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkBufferCollectionPropertiesFUCHSIA; + +typedef struct VkImageFormatConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkImageCreateInfo imageCreateInfo; + VkFormatFeatureFlags requiredFormatFeatures; + VkImageFormatConstraintsFlagsFUCHSIA flags; + uint64_t sysmemPixelFormat; + uint32_t colorSpaceCount; + const VkSysmemColorSpaceFUCHSIA* pColorSpaces; +} VkImageFormatConstraintsInfoFUCHSIA; + +typedef struct VkImageConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t formatConstraintsCount; + const VkImageFormatConstraintsInfoFUCHSIA* pFormatConstraints; + VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints; + VkImageConstraintsInfoFlagsFUCHSIA flags; +} VkImageConstraintsInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferCollectionFUCHSIA)(VkDevice device, const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferCollectionFUCHSIA* pCollection); +typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo); +typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo); +typedef void (VKAPI_PTR *PFN_vkDestroyBufferCollectionFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetBufferCollectionPropertiesFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, VkBufferCollectionPropertiesFUCHSIA* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferCollectionFUCHSIA( + VkDevice device, + const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferCollectionFUCHSIA* pCollection); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionImageConstraintsFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionBufferConstraintsFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBufferCollectionFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferCollectionPropertiesFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties); +#endif + #ifdef __cplusplus } #endif diff --git a/third_party/vulkan/vulkan_ggp.h b/third_party/vulkan/vulkan_ggp.h index 273c88005..9a6a582c5 100644 --- a/third_party/vulkan/vulkan_ggp.h +++ b/third_party/vulkan/vulkan_ggp.h @@ -2,7 +2,7 @@ #define VULKAN_GGP_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/third_party/vulkan/vulkan_ios.h b/third_party/vulkan/vulkan_ios.h index 651945cc7..6e7e6afea 100644 --- a/third_party/vulkan/vulkan_ios.h +++ b/third_party/vulkan/vulkan_ios.h @@ -2,7 +2,7 @@ #define VULKAN_IOS_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -20,7 +20,7 @@ extern "C" { #define VK_MVK_ios_surface 1 -#define VK_MVK_IOS_SURFACE_SPEC_VERSION 2 +#define VK_MVK_IOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface" typedef VkFlags VkIOSSurfaceCreateFlagsMVK; typedef struct VkIOSSurfaceCreateInfoMVK { diff --git a/third_party/vulkan/vulkan_macos.h b/third_party/vulkan/vulkan_macos.h index 3208b728e..c49b123d0 100644 --- a/third_party/vulkan/vulkan_macos.h +++ b/third_party/vulkan/vulkan_macos.h @@ -2,7 +2,7 @@ #define VULKAN_MACOS_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -20,7 +20,7 @@ extern "C" { #define VK_MVK_macos_surface 1 -#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2 +#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface" typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; typedef struct VkMacOSSurfaceCreateInfoMVK { diff --git a/third_party/vulkan/vulkan_metal.h b/third_party/vulkan/vulkan_metal.h index 99f097d95..5cf4a703a 100644 --- a/third_party/vulkan/vulkan_metal.h +++ b/third_party/vulkan/vulkan_metal.h @@ -2,7 +2,7 @@ #define VULKAN_METAL_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/third_party/vulkan/vulkan_screen.h b/third_party/vulkan/vulkan_screen.h new file mode 100644 index 000000000..92ad9bfab --- /dev/null +++ b/third_party/vulkan/vulkan_screen.h @@ -0,0 +1,54 @@ +#ifndef VULKAN_SCREEN_H_ +#define VULKAN_SCREEN_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_QNX_screen_surface 1 +#define VK_QNX_SCREEN_SURFACE_SPEC_VERSION 1 +#define VK_QNX_SCREEN_SURFACE_EXTENSION_NAME "VK_QNX_screen_surface" +typedef VkFlags VkScreenSurfaceCreateFlagsQNX; +typedef struct VkScreenSurfaceCreateInfoQNX { + VkStructureType sType; + const void* pNext; + VkScreenSurfaceCreateFlagsQNX flags; + struct _screen_context* context; + struct _screen_window* window; +} VkScreenSurfaceCreateInfoQNX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateScreenSurfaceQNX)(VkInstance instance, const VkScreenSurfaceCreateInfoQNX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct _screen_window* window); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateScreenSurfaceQNX( + VkInstance instance, + const VkScreenSurfaceCreateInfoQNX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceScreenPresentationSupportQNX( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + struct _screen_window* window); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/vulkan/vulkan_vi.h b/third_party/vulkan/vulkan_vi.h index 2e62d7d3a..9e0dcca20 100644 --- a/third_party/vulkan/vulkan_vi.h +++ b/third_party/vulkan/vulkan_vi.h @@ -2,7 +2,7 @@ #define VULKAN_VI_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/third_party/vulkan/vulkan_wayland.h b/third_party/vulkan/vulkan_wayland.h index f7b307e51..2a329be9d 100644 --- a/third_party/vulkan/vulkan_wayland.h +++ b/third_party/vulkan/vulkan_wayland.h @@ -2,7 +2,7 @@ #define VULKAN_WAYLAND_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/third_party/vulkan/vulkan_win32.h b/third_party/vulkan/vulkan_win32.h index 4b561ea10..1b680f0b1 100644 --- a/third_party/vulkan/vulkan_win32.h +++ b/third_party/vulkan/vulkan_win32.h @@ -2,7 +2,7 @@ #define VULKAN_WIN32_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/third_party/vulkan/vulkan_xcb.h b/third_party/vulkan/vulkan_xcb.h index c5441b239..5ba2ad850 100644 --- a/third_party/vulkan/vulkan_xcb.h +++ b/third_party/vulkan/vulkan_xcb.h @@ -2,7 +2,7 @@ #define VULKAN_XCB_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/third_party/vulkan/vulkan_xlib.h b/third_party/vulkan/vulkan_xlib.h index c54628a7e..75c75dc2e 100644 --- a/third_party/vulkan/vulkan_xlib.h +++ b/third_party/vulkan/vulkan_xlib.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/third_party/vulkan/vulkan_xlib_xrandr.h b/third_party/vulkan/vulkan_xlib_xrandr.h index 436432f84..fa2749342 100644 --- a/third_party/vulkan/vulkan_xlib_xrandr.h +++ b/third_party/vulkan/vulkan_xlib_xrandr.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_XRANDR_H_ 1 /* -** Copyright (c) 2015-2020 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/tools/build/bin/premake5.exe b/tools/build/bin/premake5.exe index 2a01f91d7..68a709934 100644 Binary files a/tools/build/bin/premake5.exe and b/tools/build/bin/premake5.exe differ diff --git a/xenia-build b/xenia-build index 945a545a5..671f1d7b6 100755 --- a/xenia-build +++ b/xenia-build @@ -410,14 +410,15 @@ def git_is_repository(): def git_submodule_update(): - """Runs a full recursive git submodule init and update. + """Runs a git submodule init and update. """ shell_call([ 'git', + '-c', + 'fetch.recurseSubmodules=on-demand', 'submodule', 'update', '--init', - '--recursive', ]) @@ -430,7 +431,7 @@ def get_clang_format_binary(): attempts = [ 'C:\\Program Files\\LLVM\\bin\\clang-format.exe', 'C:\\Program Files (x86)\\LLVM\\bin\\clang-format.exe', - 'clang-format-9', + 'clang-format-13', 'clang-format', ] for binary in attempts: @@ -438,7 +439,7 @@ def get_clang_format_binary(): return binary print('ERROR: clang-format is not on PATH') print('LLVM is available from https://llvm.org/releases/download.html') - print('At least version 9 is required.') + print('At least version 13 is required.') print('See docs/style_guide.md for instructions on how to get it.') sys.exit(1) @@ -902,7 +903,8 @@ class BuildShadersCommand(Command): if sys.platform == 'win32': print('Building Direct3D 12 Shader Model 5.1 DXBC shaders...') windows_sdk_bin_path = os.path.join( - os.environ['ProgramFiles(x86)'], 'Windows Kits/10/bin/x64') + os.environ['ProgramFiles(x86)'], + 'Windows Kits/10/bin/10.0.19041.0/x64') fxc = os.path.join(windows_sdk_bin_path, 'fxc') # Ensure we have the tools. if not os.path.exists(windows_sdk_bin_path): @@ -921,12 +923,16 @@ class BuildShadersCommand(Command): os.makedirs(dxbc_dir_path, exist_ok=True) dxbc_file_path_base = os.path.join(dxbc_dir_path, dxbc_identifier) + # Not enabling treating warnings as errors (/WX) because it + # overrides #pragma warning, and the FXAA shader triggers a + # bug in FXC causing an uninitialized variable warning if + # early exit from a function is done. if subprocess.call([ fxc, + '/D', 'XESL_LANGUAGE_HLSL=1', '/Fh', dxbc_file_path_base + '.h', '/T', dxbc_identifier[-2:] + '_5_1', '/Vn', dxbc_identifier, - '/WX', '/nologo', src_path ], stdout=subprocess.DEVNULL): @@ -999,6 +1005,7 @@ class GenSpirvCommand(Command): # GLSL source -> .spv binary shell_call([ glslang, + '-DXESL_LANGUAGE_GLSL=1', '-Os', '-V', src_file, '-o', spv_file,