mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-07 13:39:55 +00:00
Merge main 1e658521a0 into #9892 (fde9ff2d9a)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
commit
3c0ee17922
1068 files changed
+59831
-5025
No files matched your search
@@ -32,7 +32,7 @@ permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: build-${{ github.event_name }}-${{ github.event.pull_request.number || inputs.pr || github.ref }}
|
||||
group: build-${{ github.event_name }}-${{ github.event.pull_request.number || inputs.pr || (github.event_name == 'push' && github.sha) || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name != 'push' }}
|
||||
|
||||
env:
|
||||
@@ -56,6 +56,7 @@ jobs:
|
||||
relinker: ${{ steps.gate.outputs.relinker }}
|
||||
register-context: ${{ steps.gate.outputs.register-context }}
|
||||
write-watch: ${{ steps.gate.outputs.write-watch }}
|
||||
edge-watch: ${{ steps.gate.outputs.edge-watch }}
|
||||
mingw-host-tests: ${{ steps.gate.outputs.mingw-host-tests }}
|
||||
full: ${{ steps.gate.outputs.full }}
|
||||
relinker-hosts: ${{ steps.gate.outputs.relinker-hosts }}
|
||||
@@ -139,6 +140,8 @@ jobs:
|
||||
registerContext: edits('register-context') ||
|
||||
touches('core/libs/tests/register_context/', 'core/libs/tests/RegisterContext.cpp', libc),
|
||||
writeWatch: edits('write-watch') || touches('core/libs/tests/write_watch/', 'core/libs/tests/WriteWatch.cpp', libc),
|
||||
edgeWatch: edits('edge-watch') || touches('core/libs/tests/edge_watch/', 'core/libs/tests/EdgeWatch.cpp',
|
||||
'core/libs/prx/libkernel/Equeue/src/EdgeWatch.cpp', 'core/libs/prx/libkernel/Equeue/include/EdgeWatch.hpp', libc),
|
||||
mingwHostTests: edits('eligibility') || edits('windows') || touches(
|
||||
'core/CMakeLists.txt', 'core/libs/', 'cmake/', '3rdparty/', '.gitmodules', 'tools/build_mingw_host_only_tests.py',
|
||||
'tools/build_changed_guest_tests.py', 'tools/configure_seed.py', 'tools/select_tests.py',
|
||||
@@ -178,6 +181,7 @@ jobs:
|
||||
core.setOutput('relinker', run.relinker);
|
||||
core.setOutput('register-context', run.registerContext);
|
||||
core.setOutput('write-watch', run.writeWatch);
|
||||
core.setOutput('edge-watch', run.edgeWatch);
|
||||
core.setOutput('mingw-host-tests', false);
|
||||
core.setOutput('full', true);
|
||||
core.setOutput('relinker-hosts', relinkerHosts(true, true));
|
||||
@@ -268,6 +272,7 @@ jobs:
|
||||
core.setOutput('relinker', relinker);
|
||||
core.setOutput('register-context', registerContext);
|
||||
core.setOutput('write-watch', writeWatch);
|
||||
core.setOutput('edge-watch', run.edgeWatch);
|
||||
core.setOutput('mingw-host-tests', !manual && run.mingwHostTests);
|
||||
core.setOutput('full', full);
|
||||
core.setOutput('relinker-hosts', relinkerHosts(full, linux));
|
||||
@@ -328,10 +333,10 @@ jobs:
|
||||
- if: runner.os == 'Windows'
|
||||
run: echo 'C:\winlibs\mingw64\bin' >> "$GITHUB_PATH"
|
||||
- if: ${{ matrix.architectures == 'x86_64' }}
|
||||
run: sudo softwareupdate --install-rosetta --agree-to-license
|
||||
run: arch -x86_64 /usr/bin/true || sudo softwareupdate --install-rosetta --agree-to-license
|
||||
- run: cmake -S . -B build-relinker -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DANYPS5_RELINKER_ONLY=ON -DBUILD_TESTING=ON -DCMAKE_OSX_ARCHITECTURES=${{ matrix.architectures }}
|
||||
- run: cmake --build build-relinker --parallel 3
|
||||
- run: ctest --test-dir build-relinker --output-on-failure --timeout 120 --parallel 4
|
||||
- run: ctest --test-dir build-relinker --output-on-failure --timeout 120 --parallel 4 --no-tests=error
|
||||
|
||||
relinker-asan:
|
||||
needs: eligibility
|
||||
@@ -648,7 +653,7 @@ jobs:
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: build/externals
|
||||
key: ffmpeg-${{ runner.os }}-${{ steps.submodules.outputs.ffmpeg }}
|
||||
key: ffmpeg-${{ runner.os }}-winlibs-${{ env.WINLIBS_ZIP }}-${{ steps.submodules.outputs.ffmpeg }}
|
||||
- id: seed-cache
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
@@ -707,7 +712,7 @@ jobs:
|
||||
- name: Build and run changed guest core/libs tests
|
||||
if: github.event_name == 'pull_request'
|
||||
shell: cmd
|
||||
run: python tools/build_changed_guest_tests.py build changed.txt
|
||||
run: python tools/build_changed_guest_tests.py build changed.txt --output-log ctest.log
|
||||
- id: libs
|
||||
if: github.event_name != 'pull_request'
|
||||
shell: cmd
|
||||
@@ -736,3 +741,36 @@ jobs:
|
||||
awk '/Test +#[0-9]+: / && $NF == "sec" { for (i = 1; i <= NF; i++) if ($i ~ /^#[0-9]+:$/) name = $(i + 1); t = $(NF - 1) + 0; if (t > max[name]) max[name] = t }
|
||||
END { for (name in max) if (max[name] > 30) printf "::warning title=Slow test::%s took %.1f s on %s; tests must finish in 30 s (CONTRIBUTING.md)\n", name, max[name], ENVIRON["RUNNER_OS"] }' ctest.log
|
||||
|
||||
edge-watch:
|
||||
needs: eligibility
|
||||
if: ${{ needs.eligibility.outputs.edge-watch == 'true' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, macos-15]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ needs.eligibility.outputs.sha }}
|
||||
persist-credentials: false
|
||||
- name: Merge the pull request into main
|
||||
if: ${{ needs.eligibility.outputs.head != '' }}
|
||||
shell: bash
|
||||
env:
|
||||
PR_NUMBER: ${{ needs.eligibility.outputs.pr }}
|
||||
PR_HEAD: ${{ needs.eligibility.outputs.head }}
|
||||
run: |
|
||||
read -ra numbers <<< "$PR_NUMBER"
|
||||
read -ra heads <<< "$PR_HEAD"
|
||||
refspecs=()
|
||||
for number in "${numbers[@]}"; do refspecs+=("+refs/pull/$number/head:refs/remotes/pull/$number"); done
|
||||
git fetch --no-tags --unshallow origin "${refspecs[@]}"
|
||||
for i in "${!numbers[@]}"; do
|
||||
if [ "$(git rev-parse "refs/remotes/pull/${numbers[i]}")" != "${heads[i]}" ]; then echo "::error::Pull request #${numbers[i]} has newer commits; start a new build"; exit 1; fi
|
||||
if ! git -c user.name=ci -c user.email=ci@localhost merge --no-ff --no-edit "refs/remotes/pull/${numbers[i]}"; then echo "::error::Pull request #${numbers[i]} does not merge cleanly into main and the pull requests before it; rebase it first"; exit 1; fi
|
||||
done
|
||||
- run: cmake -S core/libs/tests/edge_watch -B build/edge-watch -DCMAKE_BUILD_TYPE=Release
|
||||
- run: cmake --build build/edge-watch --parallel
|
||||
- run: ctest --test-dir build/edge-watch --output-on-failure --repeat until-fail:3 --no-tests=error
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
run: |
|
||||
cmake -S core/libs/tests/emscripten -B build-native -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build-native --parallel 2
|
||||
ctest --test-dir build-native --output-on-failure
|
||||
ctest --test-dir build-native --output-on-failure --no-tests=error
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '26'
|
||||
@@ -40,4 +40,4 @@ jobs:
|
||||
source "$RUNNER_TEMP/emsdk/emsdk_env.sh"
|
||||
emcmake cmake -S core/libs/tests/emscripten -B build-portable -DCMAKE_BUILD_TYPE=Release -DANYPS5_NODE="$ANYPS5_TEST_NODE"
|
||||
cmake --build build-portable --parallel 2
|
||||
ctest --test-dir build-portable --output-on-failure
|
||||
ctest --test-dir build-portable --output-on-failure --no-tests=error
|
||||
@@ -16,6 +16,7 @@ jobs:
|
||||
steps:
|
||||
- env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
shell: bash
|
||||
run: |
|
||||
gh pr list -R "$GITHUB_REPOSITORY" --label stale -L 1000 --json number,labels \
|
||||
--jq '.[] | select(all(.labels[]; .name != "needs rebase")) | .number' |
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
name: Web release tools
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/web-release-tools.yml
|
||||
- demo/web/**
|
||||
- tools/build_web.py
|
||||
- tools/nid_names.py
|
||||
- tools/package_headers.py
|
||||
- tools/package_release.py
|
||||
- tools/test_web.py
|
||||
- tools/tests/test_build_web.py
|
||||
- tools/tests/test_web_release.py
|
||||
- core/relinker/relinker/tests/guest_import_fixtures.py
|
||||
- core/relinker/relinker/tests/test_guest_intel_trampolines.py
|
||||
- core/relinker/relinker/tests/test_guest_module_directories.py
|
||||
- core/relinker/relinker/tests/test_linux_load_alignment.py
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: web-release-tools-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
release-tools:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Test web library assets
|
||||
run: python3 tools/tests/test_build_web.py
|
||||
- name: Test web release packaging
|
||||
run: python3 tools/tests/test_web_release.py
|
||||
@@ -35,6 +35,8 @@ jobs:
|
||||
run: node demo/web/tests/archive-windows.test.mjs demo/web
|
||||
- name: Test archive reserved names
|
||||
run: node demo/web/tests/archive-reserved.test.mjs demo/web
|
||||
- name: Test library manifest validation
|
||||
run: node --test demo/web/tests/worker-manifest.test.mjs
|
||||
- name: Check browser module syntax
|
||||
run: |
|
||||
node --check demo/web/app.mjs
|
||||
|
||||
@@ -81,7 +81,7 @@ jobs:
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: build/externals
|
||||
key: ffmpeg-${{ runner.os }}-${{ steps.submodules.outputs.ffmpeg }}
|
||||
key: ffmpeg-${{ runner.os }}-msys2-${{ steps.submodules.outputs.ffmpeg }}
|
||||
- shell: cmd
|
||||
run: cmake -S . -B build %CONFIGURE% "-DANYPS5_AGC_EXECUTION_TESTS=F16ToF32Unpack;F64FmaSubnormals;RegistrationPrepareShutdown"
|
||||
- if: steps.ffmpeg-cache.outputs.cache-hit != 'true'
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
run: cmake --build build --target libs
|
||||
- shell: cmd
|
||||
working-directory: build
|
||||
run: ctest --output-on-failure --timeout 120 --parallel 4 --output-log ctest.log --output-junit ctest.xml
|
||||
run: ctest --output-on-failure --timeout 120 --parallel 4 --output-log ctest.log --output-junit ctest.xml --no-tests=error
|
||||
- run: python tools/check_skips.py build/ctest.xml --job windows
|
||||
- name: Report tests slower than 30 s
|
||||
if: ${{ !cancelled() }}
|
||||
|
||||
+62
-1
@@ -258,6 +258,8 @@ if(BUILD_TESTING)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_unwrap_self.py)
|
||||
add_test(NAME audit_dump COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_audit_dump.py)
|
||||
add_test(NAME ffmpeg_cache_keys COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_ffmpeg_cache_keys.py)
|
||||
foreach(shard RANGE 0 11)
|
||||
if(shard EQUAL 0)
|
||||
set(conventions_test_name conventions_function_bodies)
|
||||
@@ -272,7 +274,18 @@ if(BUILD_TESTING)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_performance_csv.py)
|
||||
set_tests_properties(performance_csv PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME conventions_wrapped_declarations COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_wrapped_declarations.py)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_wrapped_declarations.py WrappedDeclarationTests)
|
||||
set_tests_properties(conventions_wrapped_declarations PROPERTIES TIMEOUT 30)
|
||||
set(conventions_wrapped_declarations_source "${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_wrapped_declarations.py")
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${conventions_wrapped_declarations_source}")
|
||||
file(STRINGS "${conventions_wrapped_declarations_source}" conventions_wrapped_declarations_classes REGEX "^class [A-Za-z0-9_]*Tests\\(")
|
||||
foreach(test_class IN LISTS conventions_wrapped_declarations_classes)
|
||||
string(REGEX REPLACE "^class ([A-Za-z0-9_]+).*" "\\1" test_class "${test_class}")
|
||||
if(NOT test_class STREQUAL "WrappedDeclarationTests")
|
||||
add_test(NAME conventions_wrapped_declarations_${test_class} COMMAND ${Python3_EXECUTABLE} "${conventions_wrapped_declarations_source}" ${test_class})
|
||||
set_tests_properties(conventions_wrapped_declarations_${test_class} PROPERTIES TIMEOUT 30)
|
||||
endif()
|
||||
endforeach()
|
||||
add_test(NAME conventions_ci_gate COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_ci_gate.py)
|
||||
add_test(NAME preview_pad_timeline COMMAND ${Python3_EXECUTABLE}
|
||||
@@ -284,6 +297,8 @@ if(BUILD_TESTING)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_base_ref.py)
|
||||
add_test(NAME tools_configure_diff COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/tests/test_compare_configure_checks.py)
|
||||
set_tests_properties(tools_configure_diff PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME ctest_no_tests_flag COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/tests/test_ctest_no_tests_flag.py)
|
||||
set_tests_properties(ctest_no_tests_flag PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME conventions_doc_links COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_doc_links.py)
|
||||
add_test(NAME conventions_unknown_nids COMMAND ${Python3_EXECUTABLE}
|
||||
@@ -292,10 +307,18 @@ if(BUILD_TESTING)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_debt_length.py)
|
||||
add_test(NAME test_registration COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_test_registration.py)
|
||||
add_test(NAME unbuilt_exports COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_unbuilt_exports.py)
|
||||
add_test(NAME test_script_registration COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/check_test_registration.py --scripts)
|
||||
add_test(NAME tools_sanitizer_json COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_sanitizer_json.py)
|
||||
set_tests_properties(tools_sanitizer_json PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME build_eligibility COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_build_eligibility.py)
|
||||
add_test(NAME tools_release_notes_check COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_release_notes_check.py)
|
||||
set_tests_properties(tools_release_notes_check PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME check_skips_ctest COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_skips_ctest.py)
|
||||
set_tests_properties(check_skips_ctest PROPERTIES TIMEOUT 30)
|
||||
@@ -309,6 +332,8 @@ if(BUILD_TESTING)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_relinker_fuzz_fixture_warnings.py)
|
||||
add_test(NAME select_tests COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_select_tests.py)
|
||||
add_test(NAME relinker_test_step COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_relinker_test_step.py)
|
||||
add_test(NAME tools_self_inspect COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/tests/test_inspect_self.py)
|
||||
set_tests_properties(tools_self_inspect PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME check_main_sync COMMAND ${Python3_EXECUTABLE}
|
||||
@@ -372,6 +397,14 @@ if(BUILD_TESTING)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_pr_overlap_wrapped_exports.py)
|
||||
add_test(NAME pr_overlap_own_branch COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_pr_overlap_own_branch.py)
|
||||
add_test(NAME main_sync_renames COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_main_sync_renames.py RenamedPathsTests.test_feature_rename_keeps_the_original_path)
|
||||
set_tests_properties(main_sync_renames PROPERTIES TIMEOUT 20)
|
||||
foreach(test_case IN ITEMS test_feature_rename_with_detection_disabled test_main_rename_keeps_the_original_path test_main_rename_with_detection_disabled)
|
||||
add_test(NAME main_sync_renames_${test_case} COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_main_sync_renames.py RenamedPathsTests.${test_case})
|
||||
set_tests_properties(main_sync_renames_${test_case} PROPERTIES TIMEOUT 20)
|
||||
endforeach()
|
||||
add_test(NAME pr_overlap_errors COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_pr_overlap_errors.py)
|
||||
add_test(NAME pr_overlap_branch_scan COMMAND ${Python3_EXECUTABLE}
|
||||
@@ -397,6 +430,8 @@ if(BUILD_TESTING)
|
||||
add_test(NAME pad_input COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_pad_input.py)
|
||||
set_tests_properties(pad_input PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME stale_conflicts_workflow COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_stale_conflicts_workflow.py)
|
||||
add_test(NAME pad_timeline COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_pad_timeline.py)
|
||||
set_tests_properties(pad_timeline PROPERTIES TIMEOUT 20)
|
||||
@@ -450,10 +485,16 @@ if(BUILD_TESTING)
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_env_reference.py" "EnvReferenceDiffTests.${test_case}")
|
||||
set_tests_properties(conventions_env_reference_${test_case} PROPERTIES TIMEOUT 30)
|
||||
endforeach()
|
||||
add_test(NAME tools_annotation_symbols_json COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_annotation_symbols_json.py)
|
||||
set_tests_properties(tools_annotation_symbols_json PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME conventions_body_bom COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_body_bom.py)
|
||||
add_test(NAME conventions_blob_reads COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_blob_reads.py)
|
||||
add_test(NAME ab_split_csv COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_ab_split_csv.py)
|
||||
set_tests_properties(ab_split_csv PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME conventions_agent_files COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_agent_files.py)
|
||||
add_test(NAME conventions_alignment COMMAND ${Python3_EXECUTABLE}
|
||||
@@ -481,6 +522,26 @@ if(BUILD_TESTING)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
set(unwrap_self_test_source "${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_unwrap_self.py")
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${unwrap_self_test_source}")
|
||||
file(STRINGS "${unwrap_self_test_source}" unwrap_self_cases REGEX "^class |^ def test_")
|
||||
set(unwrap_self_first TRUE)
|
||||
foreach(test_case IN LISTS unwrap_self_cases)
|
||||
if(test_case MATCHES "^class ([A-Za-z0-9_]+)")
|
||||
set(unwrap_self_class "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
string(REGEX REPLACE "^ def (test_[A-Za-z0-9_]+).*" "\\1" test_case "${test_case}")
|
||||
if(unwrap_self_first)
|
||||
set_tests_properties(unwrap_self PROPERTIES
|
||||
ENVIRONMENT "UNWRAP_SELF_TEST=${unwrap_self_class}.${test_case}" TIMEOUT 30)
|
||||
set(unwrap_self_first FALSE)
|
||||
else()
|
||||
add_test(NAME unwrap_self_${unwrap_self_class}_${test_case} COMMAND ${Python3_EXECUTABLE}
|
||||
"${unwrap_self_test_source}" "${unwrap_self_class}.${test_case}")
|
||||
set_tests_properties(unwrap_self_${unwrap_self_class}_${test_case} PROPERTIES TIMEOUT 30)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
add_test(NAME tools_headers_manifest COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/tests/test_public_headers_manifest.py)
|
||||
set_tests_properties(tools_headers_manifest PROPERTIES TIMEOUT 20)
|
||||
add_test(NAME conventions_pr_template COMMAND ${Python3_EXECUTABLE}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
**English** | [Português (Brasil)](docs/user/README.pt-BR.md) | [Español](docs/user/README.es.md) | [简体中文](docs/user/README.zh-CN.md) | [Русский](docs/user/README.ru.md)
|
||||
**English** | [Português (Brasil)](docs/user/README.pt-BR.md) | [Español](docs/user/README.es.md) | [Italiano](docs/user/README.it.md) | [简体中文](docs/user/README.zh-CN.md) | [Русский](docs/user/README.ru.md)
|
||||
|
||||
# About
|
||||
|
||||
|
||||
@@ -302,6 +302,8 @@ include(prx/libSceFreeType/BuildInfo.cmake)
|
||||
|
||||
add_custom_target(libs DEPENDS ${PATCHED_OUTPUTS})
|
||||
include(prx/libSceLibreSsl/ErrorQueue.cmake)
|
||||
include(prx/libSceLibreSsl/MemoryBio.cmake)
|
||||
include(prx/libSceLibreSsl/Cmac.cmake)
|
||||
|
||||
include(prx/libSceLibreSsl/ProtocolSelection.cmake)
|
||||
|
||||
@@ -361,6 +363,16 @@ if(BUILD_TESTING)
|
||||
set_tests_properties(guest_kernel_sys_neo_mode PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel_sys>")
|
||||
endif()
|
||||
add_test_executable(guest_kernel_sys_constant_unknowns_tests tests/GuestKernelSysConstantUnknowns.cpp)
|
||||
target_include_directories(guest_kernel_sys_constant_unknowns_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(guest_kernel_sys_constant_unknowns_tests PRIVATE libkernel_sys libkernel libc)
|
||||
configure_windows_unwind(guest_kernel_sys_constant_unknowns_tests)
|
||||
add_test(NAME guest_kernel_sys_constant_unknowns COMMAND guest_kernel_sys_constant_unknowns_tests)
|
||||
set_tests_properties(guest_kernel_sys_constant_unknowns PROPERTIES TIMEOUT 20)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_kernel_sys_constant_unknowns PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel_sys>")
|
||||
endif()
|
||||
add_test_executable(nid_buffer_validation_tests nid/tests/BufferValidation.cpp)
|
||||
target_include_directories(nid_buffer_validation_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/nid/include)
|
||||
target_compile_features(nid_buffer_validation_tests PRIVATE cxx_std_20)
|
||||
@@ -687,6 +699,13 @@ if(BUILD_TESTING)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_test_executable(windows_crash_thread_name_tests tests/WindowsCrashThreadName.cpp)
|
||||
add_dependencies(windows_crash_thread_name_tests libc)
|
||||
configure_host_test_executable(windows_crash_thread_name_tests)
|
||||
add_test(NAME windows_crash_thread_name COMMAND windows_crash_thread_name_tests $<TARGET_FILE:libc>)
|
||||
set_tests_properties(windows_crash_thread_name PROPERTIES TIMEOUT 20
|
||||
PASS_REGULAR_EXPRESSION "on thread [0-9]+ 'a+Z'[^~]*thread [0-9]+ 'c+Y':"
|
||||
FAIL_REGULAR_EXPRESSION "Zb|Yd|did not fault")
|
||||
add_test_executable(windows_crash_text_tests tests/WindowsCrashText.cpp)
|
||||
add_dependencies(windows_crash_text_tests libc)
|
||||
if(MINGW)
|
||||
@@ -696,6 +715,13 @@ if(BUILD_TESTING)
|
||||
set_tests_properties(windows_crash_text PROPERTIES TIMEOUT 20
|
||||
PASS_REGULAR_EXPRESSION "faulting[^~]*FATAL: unhandled exception 0xc0000005[^~]* \\[r12\\] \"allocation failed in the heap\"[\r\n]+ \\[r13\\] u\"LowLevelFatalError \\[File:Unknown\\] \\[Line: 42\\] Out of memory\"[\r\n]+ \\[r14\\] \"PAGE END\"[.][.][.]"
|
||||
FAIL_REGULAR_EXPRESSION "\\[rbx\\] u?\"|did not fault")
|
||||
add_test_executable(windows_integer_overflow_report_tests tests/WindowsIntegerOverflowReport.cpp)
|
||||
add_dependencies(windows_integer_overflow_report_tests libc)
|
||||
configure_host_test_executable(windows_integer_overflow_report_tests)
|
||||
add_test(NAME windows_integer_overflow_report COMMAND windows_integer_overflow_report_tests $<TARGET_FILE:libc>)
|
||||
set_tests_properties(windows_integer_overflow_report PROPERTIES TIMEOUT 20
|
||||
PASS_REGULAR_EXPRESSION "dividing[^~]*FATAL: unhandled exception 0xc0000095"
|
||||
FAIL_REGULAR_EXPRESSION "did not fault")
|
||||
endif()
|
||||
|
||||
add_test_executable(guest_voice_port_attr_tests tests/GuestVoicePortAttr.cpp)
|
||||
@@ -793,7 +819,7 @@ if(BUILD_TESTING)
|
||||
target_include_directories(guest_np_common_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(guest_np_common_tests PRIVATE libSceNpCommon libkernel libc)
|
||||
configure_windows_unwind(guest_np_common_tests)
|
||||
foreach(testCase IN ITEMS ids sync clock)
|
||||
foreach(testCase IN ITEMS ids sync clock wake)
|
||||
add_test(NAME guest_np_common_${testCase} COMMAND guest_np_common_tests ${testCase})
|
||||
set_tests_properties(guest_np_common_${testCase} PROPERTIES TIMEOUT 20)
|
||||
if(WIN32)
|
||||
@@ -1116,6 +1142,16 @@ if(BUILD_TESTING)
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNpCppWebApi>")
|
||||
endif()
|
||||
|
||||
add_test_executable(guest_np_cpp_web_api_matches_tests tests/GuestNpCppWebApiMatches.cpp)
|
||||
target_include_directories(guest_np_cpp_web_api_matches_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(guest_np_cpp_web_api_matches_tests PRIVATE libSceNpCppWebApi libc)
|
||||
configure_windows_unwind(guest_np_cpp_web_api_matches_tests)
|
||||
add_test(NAME guest_np_cpp_web_api_matches COMMAND guest_np_cpp_web_api_matches_tests)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_np_cpp_web_api_matches PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNpCppWebApi>")
|
||||
endif()
|
||||
|
||||
add_test_executable(savedata_native_write_replacement_tests tests/SaveDataWriteReplacement.cpp)
|
||||
target_include_directories(savedata_native_write_replacement_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(savedata_native_write_replacement_tests PRIVATE libSceSaveData.native)
|
||||
@@ -1304,6 +1340,15 @@ if(BUILD_TESTING)
|
||||
set_tests_properties(guest_gnm_neo_default_state PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceGnmDriverForNeoMode>")
|
||||
endif()
|
||||
add_test_executable(guest_division_prx_abi_tests tests/GuestDivisionPrxAbi.cpp nid/src/NidCompute.cpp nid/src/Sha1.cpp)
|
||||
target_include_directories(guest_division_prx_abi_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/nid/include)
|
||||
configure_host_test_executable(guest_division_prx_abi_tests)
|
||||
target_link_libraries(guest_division_prx_abi_tests PRIVATE ${CMAKE_DL_LIBS})
|
||||
add_custom_target(guest_division_prx_library DEPENDS ${LIBC_PATCHED})
|
||||
add_dependencies(guest_division_prx_abi_tests guest_division_prx_library)
|
||||
add_test(NAME guest_division_prx_abi COMMAND guest_division_prx_abi_tests $<TARGET_FILE:libc> ${PATCHED_DIR}/libc.prx)
|
||||
set_tests_properties(guest_division_prx_abi PROPERTIES TIMEOUT 20)
|
||||
|
||||
endif()
|
||||
|
||||
include(prx/libSceFreeType/CurveBounds.cmake)
|
||||
|
||||
@@ -1820,6 +1820,8 @@ struct SaveDataEvent {
|
||||
std::uint8_t reserved[40];
|
||||
};
|
||||
|
||||
using SaveDataEventCallback = void (APS5_VABI *)(const SaveDataEvent* event, void* userdata);
|
||||
|
||||
struct SaveDataBackup {
|
||||
std::int32_t user_id;
|
||||
std::int32_t pad;
|
||||
@@ -1829,6 +1831,40 @@ struct SaveDataBackup {
|
||||
std::uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataCheckBackupData {
|
||||
std::int32_t user_id;
|
||||
std::int32_t pad;
|
||||
const SceSaveDataTitleId* title_id;
|
||||
const SceSaveDataDirName* dir_name;
|
||||
SaveDataParam* param;
|
||||
SaveDataIcon* icon;
|
||||
std::uint8_t reserved[32];
|
||||
};
|
||||
|
||||
struct SaveDataRestoreBackupData {
|
||||
std::int32_t user_id;
|
||||
std::int32_t pad;
|
||||
const SceSaveDataTitleId* title_id;
|
||||
const SceSaveDataDirName* dir_name;
|
||||
const void* fingerprint;
|
||||
std::uint32_t unused;
|
||||
std::uint8_t reserved[32];
|
||||
std::int32_t pad2;
|
||||
};
|
||||
static_assert(offsetof(SaveDataCheckBackupData, title_id) == 0x08);
|
||||
static_assert(offsetof(SaveDataCheckBackupData, dir_name) == 0x10);
|
||||
static_assert(offsetof(SaveDataCheckBackupData, param) == 0x18);
|
||||
static_assert(offsetof(SaveDataCheckBackupData, icon) == 0x20);
|
||||
static_assert(offsetof(SaveDataCheckBackupData, reserved) == 0x28);
|
||||
static_assert(sizeof(SaveDataCheckBackupData) == 0x48);
|
||||
static_assert(offsetof(SaveDataRestoreBackupData, title_id) == 0x08);
|
||||
static_assert(offsetof(SaveDataRestoreBackupData, dir_name) == 0x10);
|
||||
static_assert(offsetof(SaveDataRestoreBackupData, fingerprint) == 0x18);
|
||||
static_assert(offsetof(SaveDataRestoreBackupData, unused) == 0x20);
|
||||
static_assert(offsetof(SaveDataRestoreBackupData, reserved) == 0x24);
|
||||
static_assert(offsetof(SaveDataRestoreBackupData, pad2) == 0x44);
|
||||
static_assert(sizeof(SaveDataRestoreBackupData) == 0x48);
|
||||
|
||||
struct SaveDataConvert {
|
||||
std::int32_t user_id;
|
||||
std::int32_t pad;
|
||||
|
||||
@@ -188,7 +188,10 @@ std::optional<TrieLocation> FindTrie(const std::vector<std::uint8_t>& binary, co
|
||||
return found;
|
||||
}
|
||||
|
||||
void ParseTrieNode(const std::vector<std::uint8_t>& data, std::size_t start, std::size_t end, std::size_t node, std::string& prefix, std::set<std::size_t>& visited, std::vector<MachOExport>& out) {
|
||||
constexpr std::size_t kMaxExportTrieDepth = 1024;
|
||||
|
||||
void ParseTrieNode(const std::vector<std::uint8_t>& data, std::size_t start, std::size_t end, std::size_t node, std::string& prefix, std::set<std::size_t>& visited, std::vector<MachOExport>& out, std::size_t depth) {
|
||||
if (depth > kMaxExportTrieDepth) throw std::runtime_error("export trie nesting too deep");
|
||||
if (node >= end - start) throw std::runtime_error("export trie node out of bounds");
|
||||
if (!visited.insert(node).second) throw std::runtime_error("export trie has a cycle");
|
||||
std::size_t cursor = start + node;
|
||||
@@ -216,7 +219,7 @@ void ParseTrieNode(const std::vector<std::uint8_t>& data, std::size_t start, std
|
||||
const auto child = ReadUleb(data, cursor, end);
|
||||
const auto length = prefix.size();
|
||||
prefix += label;
|
||||
ParseTrieNode(data, start, end, static_cast<std::size_t>(child), prefix, visited, out);
|
||||
ParseTrieNode(data, start, end, static_cast<std::size_t>(child), prefix, visited, out, depth + 1);
|
||||
prefix.resize(length);
|
||||
}
|
||||
}
|
||||
@@ -227,7 +230,7 @@ std::vector<MachOExport> ParseTrie(const std::vector<std::uint8_t>& binary, std:
|
||||
if (size == 0) return exports;
|
||||
std::string prefix;
|
||||
std::set<std::size_t> visited;
|
||||
ParseTrieNode(binary, offset, std::size_t{offset} + size, 0, prefix, visited, exports);
|
||||
ParseTrieNode(binary, offset, std::size_t{offset} + size, 0, prefix, visited, exports, 0);
|
||||
return exports;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,9 @@ void PeNidPatcher::PatchNids(std::vector<std::uint8_t>& pe, const std::string& l
|
||||
|
||||
const std::size_t namesArrayOffset = RvaToOffset(pe, exportTable.AddressOfNames, peHeaderOffset, numberOfSections, sizeOfOptionalHeader);
|
||||
const std::size_t ordinalsArrayOffset = RvaToOffset(pe, exportTable.AddressOfNameOrdinals, peHeaderOffset, numberOfSections, sizeOfOptionalHeader);
|
||||
if (std::uint64_t{namesArrayOffset} + std::uint64_t{exportTable.NumberOfNames} * 4u > pe.size() ||
|
||||
std::uint64_t{ordinalsArrayOffset} + std::uint64_t{exportTable.NumberOfNames} * 2u > pe.size())
|
||||
throw std::runtime_error("export name tables out of file bounds");
|
||||
|
||||
std::vector<std::uint32_t> nameRvas(exportTable.NumberOfNames);
|
||||
std::vector<std::string> names(exportTable.NumberOfNames);
|
||||
|
||||
@@ -117,8 +117,8 @@ def dylib_command(path):
|
||||
return struct.pack("<IIIIII", LC_LOAD_DYLIB, size, 24, 2, 0x10000, 0x10000) + name.ljust(size - 24, b"\0")
|
||||
|
||||
|
||||
def build_dylib(exports, imports, signed=False, bind_opcodes=False):
|
||||
trie = build_trie(exports)
|
||||
def build_dylib(exports, imports, signed=False, bind_opcodes=False, trie=None):
|
||||
trie = build_trie(exports) if trie is None else trie
|
||||
fixups = build_fixups(imports)
|
||||
linkedit = bytearray(trie + fixups)
|
||||
trie_command = (struct.pack("<IIII", LC_DYLD_EXPORTS_TRIE, 16, PAGE, len(trie)))
|
||||
@@ -270,6 +270,22 @@ def check_refusals(patcher, directory):
|
||||
assert result.returncode != 0 and "signed Mach-O images cannot grow linkedit data" in result.stdout + result.stderr, (result.stdout, result.stderr)
|
||||
|
||||
|
||||
def chain_trie(depth):
|
||||
def fixed_uleb(value):
|
||||
return bytes([((value >> (7 * index)) & 0x7F) | 0x80 for index in range(4)] + [(value >> 28) & 0x7F])
|
||||
|
||||
node_size = 9
|
||||
nodes = [b"\x00\x01a\x00" + fixed_uleb(node_size * (index + 1)) for index in range(depth - 1)]
|
||||
nodes.append(b"\x02\x00\x00\x00")
|
||||
return b"".join(nodes) + bytes(-sum(map(len, nodes)) % 8)
|
||||
|
||||
|
||||
def check_deep_trie(patcher, directory):
|
||||
image = build_dylib([("_puts_nid_postfix", 0, 0x100)], [], trie=chain_trie(200000))
|
||||
result, _ = patch(patcher, directory, "deep-trie.dylib", image)
|
||||
assert result.returncode != 0 and "export trie nesting too deep" in result.stdout + result.stderr, (result.returncode, result.stdout, result.stderr)
|
||||
|
||||
|
||||
def check_short_imports(patcher, directory):
|
||||
imports = [("_sceXy", 1), ("_malloc", 2), ("_sceKernelFoo", 1), ("_sceNetRecv", 1)]
|
||||
result, path = patch(patcher, directory, "short.dylib", build_dylib([("_puts_nid_postfix", 0, 0x100)], imports))
|
||||
@@ -297,6 +313,7 @@ def main():
|
||||
check_preserved(patcher, directory)
|
||||
check_export_list(patcher, directory)
|
||||
check_refusals(patcher, directory)
|
||||
check_deep_trie(patcher, directory)
|
||||
print("NID patcher Mach-O tests passed")
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
@@ -564,6 +565,18 @@ class LibraryImportTests(unittest.TestCase):
|
||||
self.assertIn("delay-loaded", result.stdout + result.stderr)
|
||||
self.assertEqual(patched, image)
|
||||
|
||||
def test_huge_name_count_is_rejected_before_allocation(self):
|
||||
for count in (0xFFFFFFFF, 0x40000000):
|
||||
with self.subTest(count=count):
|
||||
image = self.library(["puts"])
|
||||
struct.pack_into("<I", image, 0x600 + 24, count)
|
||||
start = time.monotonic()
|
||||
result, patched = self.patch(image)
|
||||
self.assertLess(time.monotonic() - start, 10)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("export name tables out of file bounds", result.stdout + result.stderr)
|
||||
self.assertEqual(patched, image)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,272 @@
|
||||
#pragma once
|
||||
|
||||
#include "SceTypes.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI libAacsUnknown__plus_0gHTNd4xs4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__plus_3dyyKZMTyw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__plus_7ZoZWbIhlE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__plus_CiBKXuK8c8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__plus_RinEsZfOmw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__plus_XVwfwtkAi4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__minus_2QNA1pCQqU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__minus_kAJeMNy_minus_0E_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__minus_lknLNU2NAU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown__minus_xuQAxlUvmk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_0bhkzdWU6Y4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_0oisD9Dr3FI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_12CP5PHvlgs_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_15QPrQC1usM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_1CNq2v6hoig_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_1aMnfYcnn1I_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_1bzdduTshZ4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_1eNkqOSGM_plus_A_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_1hyWLxCZ_minus_X8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_1pvpAK9Rg1k_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_23BaEjHuFUA_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_2HaRuPcSWtE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_2KQWcFTN8ZE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_2YklE8dG4v8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_38ZtQUT4lMs_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_3LFB_minus_Ey4DUk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_3OYBQUy9yVI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_3ZqZuNL3qrM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_3odIlZa6t2I_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_4IQhgxl103g_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_4r3seYGdIK0_nid_no_patch();
|
||||
int APS5_VABI AacsPermissionActivate();
|
||||
int APS5_VABI libAacsUnknown_54hkTYBIxqs_nid_no_patch();
|
||||
int APS5_VABI AacsBusDecrypt();
|
||||
int APS5_VABI AacsModuleStop();
|
||||
int APS5_VABI libAacsUnknown_6ToH2wFRWf4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_6XcWJGADJeU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_753FlqNkJlM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_7ETkLi9auE0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_7KCIejRxaB0_nid_no_patch();
|
||||
int APS5_VABI AacsDecrypt();
|
||||
int APS5_VABI libAacsUnknown_7eM7N1Anox4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_7iLrHfVzuvs_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_7qIZfzr0Dgk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_85kBXEP1moE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_8Gj9M3o_minus_rrY_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_8TJlScPxUa8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_8YaNJTuYU_plus_g_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_9S1fVMePqpI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_9UJqpmNn494_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_9eTs6_minus_zAOJs_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_9rQgwWQB9NE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_AVRC3P8reF0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Apl9mjDSCE0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_B10mYlgLwMM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_BFdZY3ocsJo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_BO_plus_NBS2KrZc_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_BaMuhhCt_minus_dQ_nid_no_patch();
|
||||
int APS5_VABI AacsPermissionCheck();
|
||||
int APS5_VABI libAacsUnknown_DWJK8GjbNHo_nid_no_patch();
|
||||
int APS5_VABI AacsModuleInit();
|
||||
int APS5_VABI libAacsUnknown_EBGsSrhNRnM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_EFpFjkHGewY_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_EIEQ4mWz5sU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ELsVqt8cS3Q_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_EQWDDRWfuOU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ESDneLy_plus_ExU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ETDNd_minus_CDbkc_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_EX5Y3UepfU4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_EgaEREMnudw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_FA1OyesdYiA_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_FEgD32GcLdM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_FEi5mHUWB0M_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_FHWdAzU_minus_rRI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Fl0RrZ7B27g_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_G4zfSFYC1f8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_GD6inRSAHfo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_GWA91aXeU1Y_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_GXLnqJJ85dM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_GpsjAdWq5hk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_HXafooMuNTY_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_HhIFaBlod8A_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_HmdBrUh2Xz4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_HuTXuHqMrVE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ILwfo94p_minus_ng_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Iofb1lKwTNA_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_IxvgFI5JtxE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_JXvlGrRcNlg_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Jmviii0cDro_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_JolZPea7pio_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_JqeAwcly1Lc_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_JqrjeblDpqo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_KG5C7s3p_plus_mM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_KLxEGrIPbbo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_L6tIkKT5Vdg_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_LFpG7wYNZ_plus_I_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_LT_minus_aek5dBRQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_LTIva3bGCXI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_MCPkB4DYvAM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_MILG1Bi10BQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_MLHm3u_minus_UfPk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_MRMYIqUmmcQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_MVoCh7vg9Bk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_NK6Ke_minus_y45cI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_NL6gDScOFl8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_NOWYNS5AnRg_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_NRv4EFuYq9I_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_NSph9LkyLmI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_OI1om0rmEYk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_OOrYw04s_plus_VU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ObJaLtAn3TM_nid_no_patch();
|
||||
int APS5_VABI AacsModuleStart();
|
||||
int APS5_VABI libAacsUnknown_Ozlqilsf3Tw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_PHgHus4a3M0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_PUDoXp1l_minus_Po_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Q2eGSNdsRq0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Q3vOGHtSk9Y_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Q74CET98b04_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_QCq8qc_plus_kt7g_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_QDc8xyN5AQw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_QabaLwU3b9o_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_RI7fQrbtZko_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_RZFK7f3Oi24_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_RkkCme3dsyo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_SJ9GmthhZDk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_SjEjF5V5XHc_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_SjewOoJlr9c_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_TK5prfVU4b0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_TQCLQjHkkW0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_TuTNDTTOXHo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_U2zlEU4AhRk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_U6RAXYIdJJE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_UArM6xy6B3g_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_UMZJ2F8Lr4o_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_UqqcPoUuAqE_nid_no_patch();
|
||||
int APS5_VABI AacsPermissionGetNonce();
|
||||
int APS5_VABI libAacsUnknown_VnixdJqGnjU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_WOxxWZjZMfQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_WaOsDN_plus_9lZg_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_WknurdpKTqo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_WrEjdzfOo2I_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_XQuTyX2WprY_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_XUL7r8v2Q3Y_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_XbP3p94ujkg_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_XhMh4CEdKGU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Xokc3inTVbM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_XrkLs6PFhac_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Xy748BBvB2w_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_YDl9jLvW_plus_SM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_YOlHXj4rrzQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Yqt0NzhE_minus_eU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_Z9yhz8_plus_DS3k_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ZCRVIAxld6o_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ZEdbi75pkX0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ZUEIg4QZJ_plus_k_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ZnJgSGpLzGs_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_a3D2_minus_Eh_minus_DW8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_aOX5VPrNfqo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_aXeMNVrwOTw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_aZmsxlYbNes_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_aacj8q7PTFI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_b0ZC6N9oQlU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_bHqBriHrgXA_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_bQl9nHS7Jgg_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_bQmoqxNo0rE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_c04ksdAcncM_nid_no_patch();
|
||||
int APS5_VABI AacsSelectKeyFrom();
|
||||
int APS5_VABI libAacsUnknown_c9tUe3nNpxo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_cI0YmNGV22E_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_cnGJD38STwQ_nid_no_patch();
|
||||
int APS5_VABI AacsModuleTerm();
|
||||
int APS5_VABI libAacsUnknown_e_minus_SciZxh1HY_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_e_minus_yS_plus_nlBtlE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_e0UQuzSUkI8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_e5qwpKPf1aI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_eRXHQokealY_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_egjNL_minus_sA_minus_s0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_eoQNtjg5QyQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_f5FWQj_minus__minus_MwM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_fWmfE_minus_A0k90_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_fkra1GmOMmQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_flzhCbf4xnw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_gAV79zVGfzI_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_gPhz2sY_plus_lHM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_gTXUpBIgmcg_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_gmOvd0UR6rk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_h6JW5ZErMHE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_hDCeckXsgIw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_hFXdc25NmT4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_hWhpklSoZ7g_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_hct40EnKHyM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_i0ZMaUuKzkE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_iIgtd05IlbA_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_iJ3zPE02P1w_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_iOLQbPwqsJU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_igIuBDqdlZo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_j0quzCtmBr4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_jXZJmZu3ihs_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_jdd4KuD7bOg_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_jpKit8Qv76g_nid_no_patch();
|
||||
int APS5_VABI AacsPermissionSet();
|
||||
int APS5_VABI libAacsUnknown_kX1hCR9FDo0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_kYQis7lBy_plus_U_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_kaxfKxeOvbU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_keNMJVznBe0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_kk8ELO4Y2Fo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_l18OOzQPPKo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_l8uscgUMuWE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ldkS5zx7P6s_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_llme91x0I_minus_k_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_lq8QnjYyTGQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_mExJcLz6QWE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_mR3leJVBYbw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_mbKaZoh30DM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_mlZY17mBv9M_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_mnf5OTi_minus_urc_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_moU18PvmqEU_nid_no_patch();
|
||||
int APS5_VABI AacsPermissionInit();
|
||||
int APS5_VABI libAacsUnknown_o33b_plus_5keZic_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_oJobSSDssQw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_oU59phxP5U4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_oij_plus_E5v8qjM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_p8Lv5g5o9pY_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_p9sZ84FK_minus_qw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ptrqNcGG0eM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_qFchDSE1J3o_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_qGMyKAQhniM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_qKmr8FI7Too_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_qPi2nzCUYiQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_qpebtLhTJBc_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_r960kCkFF3I_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_rMR6nG8LdyQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_rOM7gjFX3nM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_raaoezfuSqY_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ruidkq8amJE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_s_plus_BvUCe_plus_t_plus_I_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_s6CgM5B_plus_8zc_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_sjNkMwi80Os_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_sv8IiSJQ0Mo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_tPYLJSOXQ8k_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_tWHiNKLyUn4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_uG7mSoxfjL0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ujgxfJSpLrc_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_ulInPmGONKo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_uvJDUwXFtw0_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_uvLxjEqwYKk_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_v5IGfww3qSA_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_vM2spx6P6RU_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_vcFZSn_plus_m4_minus_o_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_w4Go9bJ_minus_JGQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_x34TWztyXy8_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_x82CfygyUPA_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_xQoCQNT3skQ_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_y56l_minus_E5S0Qs_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_y5OsRUqNoX4_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_yFNWXXeNxF0_nid_no_patch();
|
||||
int APS5_VABI AacsUpdateKeyArea();
|
||||
int APS5_VABI libAacsUnknown_yZjYlfcfEFE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_yaNpz6jnOzE_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_yrqEHk366AM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_z0b7NKDfWpo_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_zgZWaxsJGyM_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_zreU_plus_KU3nLw_nid_no_patch();
|
||||
int APS5_VABI libAacsUnknown_zt4Xv_minus_4fjx0_nid_no_patch();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "prx/libAacs/include/InventoryExports.hpp"
|
||||
@@ -0,0 +1,328 @@
|
||||
#include "prx/libCss/include/InventoryExports.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include "prx/libc/include/general/ExportMacros.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI libCssUnknown__plus_zpMhCilHTQ_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("+zpMhCilHTQ", libCssUnknown__plus_zpMhCilHTQ_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown__minus_WR4_minus_J79nn0_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("-WR4-J79nn0", libCssUnknown__minus_WR4_minus_J79nn0_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_45oyUIl85dg_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("45oyUIl85dg", libCssUnknown_45oyUIl85dg_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_4qq5OHYaFU8_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("4qq5OHYaFU8", libCssUnknown_4qq5OHYaFU8_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_6BDNwI1e59c_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("6BDNwI1e59c", libCssUnknown_6BDNwI1e59c_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_6QhXfVttAyU_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("6QhXfVttAyU", libCssUnknown_6QhXfVttAyU_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_74insBAQhg8_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("74insBAQhg8", libCssUnknown_74insBAQhg8_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_7YdC9p2cTSQ_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("7YdC9p2cTSQ", libCssUnknown_7YdC9p2cTSQ_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_81obgoH2X2g_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("81obgoH2X2g", libCssUnknown_81obgoH2X2g_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_9T_minus_RYQ7HwqI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("9T-RYQ7HwqI", libCssUnknown_9T_minus_RYQ7HwqI_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_9wgr5dQqxyg_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("9wgr5dQqxyg", libCssUnknown_9wgr5dQqxyg_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_AfC4Omb8svg_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("AfC4Omb8svg", libCssUnknown_AfC4Omb8svg_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_B314wB_plus_fU6g_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("B314wB+fU6g", libCssUnknown_B314wB_plus_fU6g_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_BpqeQbNU0qo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("BpqeQbNU0qo", libCssUnknown_BpqeQbNU0qo_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_CnQiuTNrJcM_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("CnQiuTNrJcM", libCssUnknown_CnQiuTNrJcM_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_E96QCyLgJ3o_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("E96QCyLgJ3o", libCssUnknown_E96QCyLgJ3o_nid_no_patch);
|
||||
|
||||
int APS5_VABI dvdAuthInitialize() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI DvdMac() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI libCssUnknown_FTFSIzVj7gE_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("FTFSIzVj7gE", libCssUnknown_FTFSIzVj7gE_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_FsJO2R6pcFY_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("FsJO2R6pcFY", libCssUnknown_FsJO2R6pcFY_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_HaAxhqb2xoM_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("HaAxhqb2xoM", libCssUnknown_HaAxhqb2xoM_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_Hm2XEUlTjSk_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Hm2XEUlTjSk", libCssUnknown_Hm2XEUlTjSk_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_IcknOdMyfxQ_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("IcknOdMyfxQ", libCssUnknown_IcknOdMyfxQ_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_J6BYqrHA5UM_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("J6BYqrHA5UM", libCssUnknown_J6BYqrHA5UM_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_KUvq4G5VBPo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("KUvq4G5VBPo", libCssUnknown_KUvq4G5VBPo_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_LAcpQCmLWwI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("LAcpQCmLWwI", libCssUnknown_LAcpQCmLWwI_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_MRbX1Lg7JPo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("MRbX1Lg7JPo", libCssUnknown_MRbX1Lg7JPo_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_OM3ptXltjzo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("OM3ptXltjzo", libCssUnknown_OM3ptXltjzo_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_Q4g0Ji0W5GY_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Q4g0Ji0W5GY", libCssUnknown_Q4g0Ji0W5GY_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_SRPTG7u8o98_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("SRPTG7u8o98", libCssUnknown_SRPTG7u8o98_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_TJdtvWbNKhs_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("TJdtvWbNKhs", libCssUnknown_TJdtvWbNKhs_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_UCT_minus_EFL9GlY_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("UCT-EFL9GlY", libCssUnknown_UCT_minus_EFL9GlY_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_UlBK7McbIBI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("UlBK7McbIBI", libCssUnknown_UlBK7McbIBI_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_VLaRWTMO9U8_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("VLaRWTMO9U8", libCssUnknown_VLaRWTMO9U8_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_VMBVlZevTLw_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("VMBVlZevTLw", libCssUnknown_VMBVlZevTLw_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_Wdf6DHvrt4g_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Wdf6DHvrt4g", libCssUnknown_Wdf6DHvrt4g_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_X9dl5pCTGiE_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("X9dl5pCTGiE", libCssUnknown_X9dl5pCTGiE_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_XWqQyI3K47s_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("XWqQyI3K47s", libCssUnknown_XWqQyI3K47s_nid_no_patch);
|
||||
|
||||
int APS5_VABI dvdAuthFinalize() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI libCssUnknown_bQpZTilHSL0_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("bQpZTilHSL0", libCssUnknown_bQpZTilHSL0_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_cN12O1uQ6Fo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("cN12O1uQ6Fo", libCssUnknown_cN12O1uQ6Fo_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_cTnMCeNpGqc_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("cTnMCeNpGqc", libCssUnknown_cTnMCeNpGqc_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_czKT3U30FFE_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("czKT3U30FFE", libCssUnknown_czKT3U30FFE_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_daklpMlbo00_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("daklpMlbo00", libCssUnknown_daklpMlbo00_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_f7iq9LsamYo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("f7iq9LsamYo", libCssUnknown_f7iq9LsamYo_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_gbja3RUMWJ4_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("gbja3RUMWJ4", libCssUnknown_gbja3RUMWJ4_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_giIpEkyo9Hg_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("giIpEkyo9Hg", libCssUnknown_giIpEkyo9Hg_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_hD3HhdNG_plus_xw_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("hD3HhdNG+xw", libCssUnknown_hD3HhdNG_plus_xw_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_hbTTMmwE3lo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("hbTTMmwE3lo", libCssUnknown_hbTTMmwE3lo_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_hbvafh9uQqY_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("hbvafh9uQqY", libCssUnknown_hbvafh9uQqY_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_jYGAlLsijgw_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("jYGAlLsijgw", libCssUnknown_jYGAlLsijgw_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_k1_plus_Z1AtnLYI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("k1+Z1AtnLYI", libCssUnknown_k1_plus_Z1AtnLYI_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_k5AW5Xs4aqg_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("k5AW5Xs4aqg", libCssUnknown_k5AW5Xs4aqg_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_kc5B1ELiUv4_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("kc5B1ELiUv4", libCssUnknown_kc5B1ELiUv4_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_nhK3hP3XL3Y_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("nhK3hP3XL3Y", libCssUnknown_nhK3hP3XL3Y_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_ohRg1gu5G1w_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("ohRg1gu5G1w", libCssUnknown_ohRg1gu5G1w_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_pTycImStaM4_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("pTycImStaM4", libCssUnknown_pTycImStaM4_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_rylZqUytLj8_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("rylZqUytLj8", libCssUnknown_rylZqUytLj8_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_szOnkd_plus_7b3U_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("szOnkd+7b3U", libCssUnknown_szOnkd_plus_7b3U_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_utwkEaQy6D4_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("utwkEaQy6D4", libCssUnknown_utwkEaQy6D4_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_wDe5E_minus_Nfd7E_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("wDe5E-Nfd7E", libCssUnknown_wDe5E_minus_Nfd7E_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_xQX0HWKQKDA_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("xQX0HWKQKDA", libCssUnknown_xQX0HWKQKDA_nid_no_patch);
|
||||
|
||||
int APS5_VABI libCssUnknown_z4KQSeB3_plus_6U_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("z4KQSeB3+6U", libCssUnknown_z4KQSeB3_plus_6U_nid_no_patch);
|
||||
|
||||
int APS5_VABI CpsInitKey() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI libCssUnknown_zxv6uaL0lAs_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("zxv6uaL0lAs", libCssUnknown_zxv6uaL0lAs_nid_no_patch);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "SceTypes.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI libCssUnknown__plus_zpMhCilHTQ_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown__minus_WR4_minus_J79nn0_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_45oyUIl85dg_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_4qq5OHYaFU8_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_6BDNwI1e59c_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_6QhXfVttAyU_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_74insBAQhg8_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_7YdC9p2cTSQ_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_81obgoH2X2g_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_9T_minus_RYQ7HwqI_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_9wgr5dQqxyg_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_AfC4Omb8svg_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_B314wB_plus_fU6g_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_BpqeQbNU0qo_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_CnQiuTNrJcM_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_E96QCyLgJ3o_nid_no_patch();
|
||||
int APS5_VABI dvdAuthInitialize();
|
||||
int APS5_VABI DvdMac();
|
||||
int APS5_VABI libCssUnknown_FTFSIzVj7gE_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_FsJO2R6pcFY_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_HaAxhqb2xoM_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_Hm2XEUlTjSk_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_IcknOdMyfxQ_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_J6BYqrHA5UM_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_KUvq4G5VBPo_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_LAcpQCmLWwI_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_MRbX1Lg7JPo_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_OM3ptXltjzo_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_Q4g0Ji0W5GY_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_SRPTG7u8o98_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_TJdtvWbNKhs_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_UCT_minus_EFL9GlY_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_UlBK7McbIBI_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_VLaRWTMO9U8_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_VMBVlZevTLw_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_Wdf6DHvrt4g_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_X9dl5pCTGiE_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_XWqQyI3K47s_nid_no_patch();
|
||||
int APS5_VABI dvdAuthFinalize();
|
||||
int APS5_VABI libCssUnknown_bQpZTilHSL0_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_cN12O1uQ6Fo_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_cTnMCeNpGqc_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_czKT3U30FFE_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_daklpMlbo00_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_f7iq9LsamYo_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_gbja3RUMWJ4_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_giIpEkyo9Hg_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_hD3HhdNG_plus_xw_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_hbTTMmwE3lo_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_hbvafh9uQqY_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_jYGAlLsijgw_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_k1_plus_Z1AtnLYI_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_k5AW5Xs4aqg_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_kc5B1ELiUv4_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_nhK3hP3XL3Y_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_ohRg1gu5G1w_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_pTycImStaM4_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_rylZqUytLj8_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_szOnkd_plus_7b3U_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_utwkEaQy6D4_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_wDe5E_minus_Nfd7E_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_xQX0HWKQKDA_nid_no_patch();
|
||||
int APS5_VABI libCssUnknown_z4KQSeB3_plus_6U_nid_no_patch();
|
||||
int APS5_VABI CpsInitKey();
|
||||
int APS5_VABI libCssUnknown_zxv6uaL0lAs_nid_no_patch();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "prx/libCss/include/InventoryExports.hpp"
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
APS5_DUMMY_FUN
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
@@ -0,0 +1,251 @@
|
||||
#include "prx/libc/include/general/ExportMacros.hpp"
|
||||
#include "prx/libReactNative.Modules.Vsh.WebAppLauncher/include/InventoryExports.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI CheckSystemEvents() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CommerceDialogBrowseCategory() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CommerceDialogBrowseProduct() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CommerceDialogInit() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CommerceDialogRedeemPromotionCode() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CommerceHidePsStoreIcon() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CommerceSetPsStoreIconLayout() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CommerceShowPsStoreIcon() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI DisableSystemMedia() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI ErrorDialogClose() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI ErrorDialogInit() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI ErrorDialogOpen() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetAccountAgeA() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetAccountCountryA() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetAccountIdA() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetAccountLanguage2() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetAuthorizationCode() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetClosedCaptionSettings() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetOnlineId() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetProcessTime() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetVideoOutputStatus() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetVideoOutputStatusInt() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI Hide() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI IsDebuggingSupported() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpWebAbortRequest() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpWebDeleteRequest() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpWebInitialize() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpWebReadData() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpWebTerminate() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI OpenClosedCaptionAdvancedSettings() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI OpenClosedCaptionSettings() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SoundInitialize() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SoundLoad() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SoundPlay() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SoundTerminate() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SpeechCancel() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SpeechClose() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SpeechInitialize() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SpeechSpeak() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SpeechStatus() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SpeechTerminate() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SystemDialogInit() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SystemDialogOpen() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SystemServiceParamGetInt() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI SystemServiceParamGetString() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory__plus_ucrAt9fI7c_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("+ucrAt9fI7c", libReactNativeWebAppLauncherInventory__plus_ucrAt9fI7c_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_06N_minus_dAyE_plus_HY_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("06N-dAyE+HY", libReactNativeWebAppLauncherInventory_06N_minus_dAyE_plus_HY_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_41blU2JCqLQ_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("41blU2JCqLQ", libReactNativeWebAppLauncherInventory_41blU2JCqLQ_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_BGgSEXB1Now_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("BGgSEXB1Now", libReactNativeWebAppLauncherInventory_BGgSEXB1Now_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_CAK_minus_S2JVdsk_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("CAK-S2JVdsk", libReactNativeWebAppLauncherInventory_CAK_minus_S2JVdsk_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_QxCdpkEsOgo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("QxCdpkEsOgo", libReactNativeWebAppLauncherInventory_QxCdpkEsOgo_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_Tjj_plus__plus_S2qvOU_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Tjj++S2qvOU", libReactNativeWebAppLauncherInventory_Tjj_plus__plus_S2qvOU_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_f5NHqUziG_plus_4_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("f5NHqUziG+4", libReactNativeWebAppLauncherInventory_f5NHqUziG_plus_4_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_mI_minus_ltMuVN_plus_Q_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("mI-ltMuVN+Q", libReactNativeWebAppLauncherInventory_mI_minus_ltMuVN_plus_Q_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_vDup_plus_0mWZf8_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("vDup+0mWZf8", libReactNativeWebAppLauncherInventory_vDup_plus_0mWZf8_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_wR1ucKGDM9Q_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("wR1ucKGDM9Q", libReactNativeWebAppLauncherInventory_wR1ucKGDM9Q_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_xPA_minus_tXzPGpc_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("xPA-tXzPGpc", libReactNativeWebAppLauncherInventory_xPA_minus_tXzPGpc_nid_no_patch);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include "SceTypes.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI CheckSystemEvents();
|
||||
int APS5_VABI CommerceDialogBrowseCategory();
|
||||
int APS5_VABI CommerceDialogBrowseProduct();
|
||||
int APS5_VABI CommerceDialogInit();
|
||||
int APS5_VABI CommerceDialogRedeemPromotionCode();
|
||||
int APS5_VABI CommerceHidePsStoreIcon();
|
||||
int APS5_VABI CommerceSetPsStoreIconLayout();
|
||||
int APS5_VABI CommerceShowPsStoreIcon();
|
||||
int APS5_VABI DisableSystemMedia();
|
||||
int APS5_VABI ErrorDialogClose();
|
||||
int APS5_VABI ErrorDialogInit();
|
||||
int APS5_VABI ErrorDialogOpen();
|
||||
int APS5_VABI GetAccountAgeA();
|
||||
int APS5_VABI GetAccountCountryA();
|
||||
int APS5_VABI GetAccountIdA();
|
||||
int APS5_VABI GetAccountLanguage2();
|
||||
int APS5_VABI GetAuthorizationCode();
|
||||
int APS5_VABI GetClosedCaptionSettings();
|
||||
int APS5_VABI GetOnlineId();
|
||||
int APS5_VABI GetProcessTime();
|
||||
int APS5_VABI GetVideoOutputStatus();
|
||||
int APS5_VABI GetVideoOutputStatusInt();
|
||||
int APS5_VABI Hide();
|
||||
int APS5_VABI IsDebuggingSupported();
|
||||
int APS5_VABI NpWebAbortRequest();
|
||||
int APS5_VABI NpWebDeleteRequest();
|
||||
int APS5_VABI NpWebInitialize();
|
||||
int APS5_VABI NpWebReadData();
|
||||
int APS5_VABI NpWebTerminate();
|
||||
int APS5_VABI OpenClosedCaptionAdvancedSettings();
|
||||
int APS5_VABI OpenClosedCaptionSettings();
|
||||
int APS5_VABI SoundInitialize();
|
||||
int APS5_VABI SoundLoad();
|
||||
int APS5_VABI SoundPlay();
|
||||
int APS5_VABI SoundTerminate();
|
||||
int APS5_VABI SpeechCancel();
|
||||
int APS5_VABI SpeechClose();
|
||||
int APS5_VABI SpeechInitialize();
|
||||
int APS5_VABI SpeechSpeak();
|
||||
int APS5_VABI SpeechStatus();
|
||||
int APS5_VABI SpeechTerminate();
|
||||
int APS5_VABI SystemDialogInit();
|
||||
int APS5_VABI SystemDialogOpen();
|
||||
int APS5_VABI SystemServiceParamGetInt();
|
||||
int APS5_VABI SystemServiceParamGetString();
|
||||
|
||||
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory__plus_ucrAt9fI7c_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_06N_minus_dAyE_plus_HY_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_41blU2JCqLQ_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_BGgSEXB1Now_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_CAK_minus_S2JVdsk_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_QxCdpkEsOgo_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_Tjj_plus__plus_S2qvOU_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_f5NHqUziG_plus_4_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_mI_minus_ltMuVN_plus_Q_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_vDup_plus_0mWZf8_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_wR1ucKGDM9Q_nid_no_patch();
|
||||
int APS5_VABI libReactNativeWebAppLauncherInventory_xPA_minus_tXzPGpc_nid_no_patch();
|
||||
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "prx/libReactNative.Modules.Vsh.WebAppLauncher/include/InventoryExports.hpp"
|
||||
@@ -0,0 +1,361 @@
|
||||
#include "prx/libc/include/general/ExportMacros.hpp"
|
||||
#include "prx/libReactNative.Modules.Vsh/include/InventoryExports.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI CreateWebApiLibCtx() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CryptographyDecryptAES128CBC() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CryptographyDecryptAES128CBC_HS256() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CryptographyDecryptAES128GCM() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CryptographyEncryptAES128CBC() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CryptographyEncryptAES128GCM() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI CryptographyGenerateHmacSha256() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI DestroyWebApiLibCtx() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetLibHttpCtxId() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI GetPs4AppCategoryForTitleId() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI InetStatGetResultNative() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI InetStatGetStateNative() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI InetStatStartTestNative() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI InitializeNetLib() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI LoginMgrCreateUser() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI LoginMgrDestroyUser() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI LoginMgrInitialize() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI LoginMgrSetLoginFlag() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI LoginMgrSetUserStatus() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI LoginMgrTerminate() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpStateManagerRegisterCallback() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpStateManagerRtcSetTick() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpStateManagerStart() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpStateManagerStop() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI NpStateManagerUnregisterCallback() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI PSNowGetStatus() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI PSNowGetStreamingStatus() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI PSNowInitialize() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI PSNowReset() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI PSNowSendCommand() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI PSNowSetAuthCodes() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI PSNowSetSettings() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI PSNowTerminate() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayClearConnectHistory() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayConfirmDeviceRegist() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayDisconnect() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayGeneratePinCode() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayGetConnectHistory() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayGetConnectUserId() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayGetConnectionStatus() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayGetRemoteplayStatus() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayGetRpMode() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayIsRemotePlaying() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayNotifyCanWakeup() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayNotifyPinCodeError() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayNotifyUserDelete() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlayProhibitStreaming() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlaySetProhibition() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlaySetProhibitionForVsh() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RemotePlaySetRpMode() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RtcGetCurrentAdNetworkTickNative() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RtcGetCurrentDebugNetworkTickNative() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI RtcGetCurrentNetworkTickNative() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI TerminateNetLib() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI WebBrowserGetEnvelopeData() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientAddEventListener() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientAttachVirtualMicrophone() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientDetachVirtualMicrophone() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientGetClientStatus() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientInitialize() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientRemoveController() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientShowHomeScreen() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientStartMicCapture() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientStopMicCapture() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceRemotePlayClientTerminateStreaming() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory__plus_I5sPs9FLXw_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("+I5sPs9FLXw", libReactNativeModulesVshInventory__plus_I5sPs9FLXw_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory__minus_9hYGDAsb4E_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("-9hYGDAsb4E", libReactNativeModulesVshInventory__minus_9hYGDAsb4E_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_BzJsgzD97LU_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("BzJsgzD97LU", libReactNativeModulesVshInventory_BzJsgzD97LU_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_IQNf2nnftNI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("IQNf2nnftNI", libReactNativeModulesVshInventory_IQNf2nnftNI_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_N3mcm_minus_qDFR0_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("N3mcm-qDFR0", libReactNativeModulesVshInventory_N3mcm_minus_qDFR0_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_OME2Be_plus_FlwA_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("OME2Be+FlwA", libReactNativeModulesVshInventory_OME2Be_plus_FlwA_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_PLEe_minus_toB_minus_KE_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("PLEe-toB-KE", libReactNativeModulesVshInventory_PLEe_minus_toB_minus_KE_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_QGGsQrtLW9Y_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("QGGsQrtLW9Y", libReactNativeModulesVshInventory_QGGsQrtLW9Y_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_Rm_plus_rgnBoPIE_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Rm+rgnBoPIE", libReactNativeModulesVshInventory_Rm_plus_rgnBoPIE_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_SJU_plus_qK_plus_8yrM_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("SJU+qK+8yrM", libReactNativeModulesVshInventory_SJU_plus_qK_plus_8yrM_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_T7dL_minus_hEySvU_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("T7dL-hEySvU", libReactNativeModulesVshInventory_T7dL_minus_hEySvU_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_b_plus_MJDz3HB6s_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("b+MJDz3HB6s", libReactNativeModulesVshInventory_b_plus_MJDz3HB6s_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_bbsP8_minus_e8GZA_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("bbsP8-e8GZA", libReactNativeModulesVshInventory_bbsP8_minus_e8GZA_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_fxEQAPDRhLw_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("fxEQAPDRhLw", libReactNativeModulesVshInventory_fxEQAPDRhLw_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_j917Pp4k_minus_CI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("j917Pp4k-CI", libReactNativeModulesVshInventory_j917Pp4k_minus_CI_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_lZ_minus_JDEqB34k_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("lZ-JDEqB34k", libReactNativeModulesVshInventory_lZ_minus_JDEqB34k_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_tKy_minus_Qdg_plus_FRc_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("tKy-Qdg+FRc", libReactNativeModulesVshInventory_tKy_minus_Qdg_plus_FRc_nid_no_patch);
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory_uQfQgwm36L4_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("uQfQgwm36L4", libReactNativeModulesVshInventory_uQfQgwm36L4_nid_no_patch);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
|
||||
#include "SceTypes.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI CreateWebApiLibCtx();
|
||||
int APS5_VABI CryptographyDecryptAES128CBC();
|
||||
int APS5_VABI CryptographyDecryptAES128CBC_HS256();
|
||||
int APS5_VABI CryptographyDecryptAES128GCM();
|
||||
int APS5_VABI CryptographyEncryptAES128CBC();
|
||||
int APS5_VABI CryptographyEncryptAES128GCM();
|
||||
int APS5_VABI CryptographyGenerateHmacSha256();
|
||||
int APS5_VABI DestroyWebApiLibCtx();
|
||||
int APS5_VABI GetLibHttpCtxId();
|
||||
int APS5_VABI GetPs4AppCategoryForTitleId();
|
||||
int APS5_VABI InetStatGetResultNative();
|
||||
int APS5_VABI InetStatGetStateNative();
|
||||
int APS5_VABI InetStatStartTestNative();
|
||||
int APS5_VABI InitializeNetLib();
|
||||
int APS5_VABI LoginMgrCreateUser();
|
||||
int APS5_VABI LoginMgrDestroyUser();
|
||||
int APS5_VABI LoginMgrInitialize();
|
||||
int APS5_VABI LoginMgrSetLoginFlag();
|
||||
int APS5_VABI LoginMgrSetUserStatus();
|
||||
int APS5_VABI LoginMgrTerminate();
|
||||
int APS5_VABI NpStateManagerRegisterCallback();
|
||||
int APS5_VABI NpStateManagerRtcSetTick();
|
||||
int APS5_VABI NpStateManagerStart();
|
||||
int APS5_VABI NpStateManagerStop();
|
||||
int APS5_VABI NpStateManagerUnregisterCallback();
|
||||
int APS5_VABI PSNowGetStatus();
|
||||
int APS5_VABI PSNowGetStreamingStatus();
|
||||
int APS5_VABI PSNowInitialize();
|
||||
int APS5_VABI PSNowReset();
|
||||
int APS5_VABI PSNowSendCommand();
|
||||
int APS5_VABI PSNowSetAuthCodes();
|
||||
int APS5_VABI PSNowSetSettings();
|
||||
int APS5_VABI PSNowTerminate();
|
||||
int APS5_VABI RemotePlayClearConnectHistory();
|
||||
int APS5_VABI RemotePlayConfirmDeviceRegist();
|
||||
int APS5_VABI RemotePlayDisconnect();
|
||||
int APS5_VABI RemotePlayGeneratePinCode();
|
||||
int APS5_VABI RemotePlayGetConnectHistory();
|
||||
int APS5_VABI RemotePlayGetConnectUserId();
|
||||
int APS5_VABI RemotePlayGetConnectionStatus();
|
||||
int APS5_VABI RemotePlayGetRemoteplayStatus();
|
||||
int APS5_VABI RemotePlayGetRpMode();
|
||||
int APS5_VABI RemotePlayIsRemotePlaying();
|
||||
int APS5_VABI RemotePlayNotifyCanWakeup();
|
||||
int APS5_VABI RemotePlayNotifyPinCodeError();
|
||||
int APS5_VABI RemotePlayNotifyUserDelete();
|
||||
int APS5_VABI RemotePlayProhibitStreaming();
|
||||
int APS5_VABI RemotePlaySetProhibition();
|
||||
int APS5_VABI RemotePlaySetProhibitionForVsh();
|
||||
int APS5_VABI RemotePlaySetRpMode();
|
||||
int APS5_VABI RtcGetCurrentAdNetworkTickNative();
|
||||
int APS5_VABI RtcGetCurrentDebugNetworkTickNative();
|
||||
int APS5_VABI RtcGetCurrentNetworkTickNative();
|
||||
int APS5_VABI TerminateNetLib();
|
||||
int APS5_VABI WebBrowserGetEnvelopeData();
|
||||
int APS5_VABI sceRemotePlayClientAddEventListener();
|
||||
int APS5_VABI sceRemotePlayClientAttachVirtualMicrophone();
|
||||
int APS5_VABI sceRemotePlayClientDetachVirtualMicrophone();
|
||||
int APS5_VABI sceRemotePlayClientGetClientStatus();
|
||||
int APS5_VABI sceRemotePlayClientInitialize();
|
||||
int APS5_VABI sceRemotePlayClientRemoveController();
|
||||
int APS5_VABI sceRemotePlayClientShowHomeScreen();
|
||||
int APS5_VABI sceRemotePlayClientStartMicCapture();
|
||||
int APS5_VABI sceRemotePlayClientStopMicCapture();
|
||||
int APS5_VABI sceRemotePlayClientTerminateStreaming();
|
||||
|
||||
|
||||
int APS5_VABI libReactNativeModulesVshInventory__plus_I5sPs9FLXw_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory__minus_9hYGDAsb4E_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_BzJsgzD97LU_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_IQNf2nnftNI_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_N3mcm_minus_qDFR0_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_OME2Be_plus_FlwA_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_PLEe_minus_toB_minus_KE_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_QGGsQrtLW9Y_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_Rm_plus_rgnBoPIE_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_SJU_plus_qK_plus_8yrM_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_T7dL_minus_hEySvU_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_b_plus_MJDz3HB6s_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_bbsP8_minus_e8GZA_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_fxEQAPDRhLw_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_j917Pp4k_minus_CI_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_lZ_minus_JDEqB34k_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_tKy_minus_Qdg_plus_FRc_nid_no_patch();
|
||||
int APS5_VABI libReactNativeModulesVshInventory_uQfQgwm36L4_nid_no_patch();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "prx/libReactNative.Modules.Vsh/include/InventoryExports.hpp"
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "prx/libSceAbstractStorage/include/Api.hpp"
|
||||
#include "prx/libSceAbstractStorage/include/LegacyExports.hpp"
|
||||
#include "prx/libc/include/general/ExportMacros.hpp"
|
||||
#include "prx/libSceAbstractStorage/include/InventoryExports.hpp"
|
||||
@@ -9,555 +10,445 @@
|
||||
extern "C" {
|
||||
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_7RnkdybfYiQ_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage12Serializable12readExternalESt10shared_ptrINS_7ContentEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("7RnkdybfYiQ", sceAbstractStorageUnknown_7RnkdybfYiQ_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_gINcKTbrqk4_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage12Serializable13writeExternalESt10shared_ptrINS_7ContentEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("gINcKTbrqk4", sceAbstractStorageUnknown_gINcKTbrqk4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_F6tunp5_4ZM_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage12SerializableC1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("F6tunp5+4ZM", sceAbstractStorageUnknown_F6tunp5_4ZM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_QRnz_VjPrkY_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage12SerializableC2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("QRnz-VjPrkY", sceAbstractStorageUnknown_QRnz_VjPrkY_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_DkAGX6EPi_g_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage12SerializableD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("DkAGX6EPi+g", sceAbstractStorageUnknown_DkAGX6EPi_g_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_tDhVqVa_tvU_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage12SerializableD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("tDhVqVa-tvU", sceAbstractStorageUnknown_tDhVqVa_tvU_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_o9RD998mN8M_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent12readExternalESt10shared_ptrINS_7ContentEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("o9RD998mN8M", sceAbstractStorageUnknown_o9RD998mN8M_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_KAJD5gNtjzg_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent13writeExternalESt10shared_ptrINS_7ContentEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("KAJD5gNtjzg", sceAbstractStorageUnknown_KAJD5gNtjzg_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_jekg6a2C_KE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent14CreateInstanceESbIcSt11char_traitsIcENS_8StlAllocIcEEEN3paf6common9SharedPtrINS6_6BufferEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("jekg6a2C-KE", sceAbstractStorageUnknown_jekg6a2C_KE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_SPPYTszg6LQ_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent14CreateInstanceESbIcSt11char_traitsIcENS_8StlAllocIcEEEPvm() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("SPPYTszg6LQ", sceAbstractStorageUnknown_SPPYTszg6LQ_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_ppyod3XEauc_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent4OpenEit() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("ppyod3XEauc", sceAbstractStorageUnknown_ppyod3XEauc_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_FC7E1riolAM_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent4ReadEPvlPl() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("FC7E1riolAM", sceAbstractStorageUnknown_FC7E1riolAM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_h64Ojqk4fbE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent5CloseEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("h64Ojqk4fbE", sceAbstractStorageUnknown_h64Ojqk4fbE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_L9n8X5qE3gI_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent5FlushEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("L9n8X5qE3gI", sceAbstractStorageUnknown_L9n8X5qE3gI_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_UqSO97fYNAs_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent5WriteEPKvlPl() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("UqSO97fYNAs", sceAbstractStorageUnknown_UqSO97fYNAs_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_nxefs8JHV5U_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent6RemoveEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("nxefs8JHV5U", sceAbstractStorageUnknown_nxefs8JHV5U_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_TI_djeSDh5s_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent8SeekByteEliPl() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("TI+djeSDh5s", sceAbstractStorageUnknown_TI_djeSDh5s_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_23QZTBt3E60_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent8SeekTimeElPl() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("23QZTBt3E60", sceAbstractStorageUnknown_23QZTBt3E60_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_CgSbdJjHTyc_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentC1ESbIcSt11char_traitsIcENS_8StlAllocIcEEEN3paf6common9SharedPtrINS6_6BufferEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("CgSbdJjHTyc", sceAbstractStorageUnknown_CgSbdJjHTyc_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_uhxDqVGiDTY_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentC2ESbIcSt11char_traitsIcENS_8StlAllocIcEEEN3paf6common9SharedPtrINS6_6BufferEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("uhxDqVGiDTY", sceAbstractStorageUnknown_uhxDqVGiDTY_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_93IuLXtj1sc_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("93IuLXtj1sc", sceAbstractStorageUnknown_93IuLXtj1sc_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_6g_lsIudFQY_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("6g-lsIudFQY", sceAbstractStorageUnknown_6g_lsIudFQY_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_r_kkC2OXw10_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("r+kkC2OXw10", sceAbstractStorageUnknown_r_kkC2OXw10_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_xeunZETVUSk_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager10GetStorageERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEPSt10shared_ptrINS_7StorageEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("xeunZETVUSk", sceAbstractStorageUnknown_xeunZETVUSk_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_k0BKafeYaUo_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager10InitializeEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("k0BKafeYaUo", sceAbstractStorageUnknown_k0BKafeYaUo_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_iAN_9pPHZSE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager11GetInstanceERNS_12MemAllocatorEPv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("iAN-9pPHZSE", sceAbstractStorageUnknown_iAN_9pPHZSE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_QbKmf_2_cR0_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager11GetInstanceEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("QbKmf+2+cR0", sceAbstractStorageUnknown_QbKmf_2_cR0_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_JWT7NbPA9Ds_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager12NotifyCreateERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEb() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("JWT7NbPA9Ds", sceAbstractStorageUnknown_JWT7NbPA9Ds_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown__fMkDXxU9E0_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager12NotifyRemoveERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEb() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("+fMkDXxU9E0", sceAbstractStorageUnknown__fMkDXxU9E0_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_sFN0uAZmk04_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager15ReleaseInstanceEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("sFN0uAZmk04", sceAbstractStorageUnknown_sFN0uAZmk04_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_wvDKH1RiZhU_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager16NotifyWriteCloseERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("wvDKH1RiZhU", sceAbstractStorageUnknown_wvDKH1RiZhU_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_FxOHF0FBNfU_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager16RegisterListenerEPNS_17ItemEventListenerE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("FxOHF0FBNfU", sceAbstractStorageUnknown_FxOHF0FBNfU_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_JvyLbYhVigM_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager16RegisterListenerEPNS_20StorageEventListenerE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("JvyLbYhVigM", sceAbstractStorageUnknown_JvyLbYhVigM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_bb_T5NMDPck_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager16get_storage_nameERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("bb-T5NMDPck", sceAbstractStorageUnknown_bb_T5NMDPck_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_LPRr40DzhbA_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager17NotifySetMetadataERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("LPRr40DzhbA", sceAbstractStorageUnknown_LPRr40DzhbA_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_oIR7L2c6df8_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager18GetStorageNameListEPSt6vectorISbIcSt11char_traitsIcENS_8StlAllocIcEEESaIS6_EE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("oIR7L2c6df8", sceAbstractStorageUnknown_oIR7L2c6df8_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_mhLGIWhMLlk_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager18UnregisterListenerEPKNS_17ItemEventListenerE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("mhLGIWhMLlk", sceAbstractStorageUnknown_mhLGIWhMLlk_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_0Ydc18_XsSw_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager18UnregisterListenerEPKNS_20StorageEventListenerE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("0Ydc18+XsSw", sceAbstractStorageUnknown_0Ydc18_XsSw_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_piG6ktf2BTU_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager20get_service_instanceENS_11ServiceTypeE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("piG6ktf2BTU", sceAbstractStorageUnknown_piG6ktf2BTU_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_iLakkVdPya4_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager21NotifyStorageAttachedERKSbIcSt11char_traitsIcENS_8StlAllocIcEEENS_11ServiceTypeE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("iLakkVdPya4", sceAbstractStorageUnknown_iLakkVdPya4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_1Ko_sKZgqqs_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager21NotifyStorageDetachedERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("1Ko+sKZgqqs", sceAbstractStorageUnknown_1Ko_sKZgqqs_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown__PYC3_W6yUE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager4FreeEPv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("-PYC3+W6yUE", sceAbstractStorageUnknown__PYC3_W6yUE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_3iP9Xa6Z3z0_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager4LoadENS_11ServiceTypeE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("3iP9Xa6Z3z0", sceAbstractStorageUnknown_3iP9Xa6Z3z0_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_JREmVpFIgEY_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager6MallocEm() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("JREmVpFIgEY", sceAbstractStorageUnknown_JREmVpFIgEY_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_kCX0k5t1v_w_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager6UnloadENS_11ServiceTypeE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("kCX0k5t1v-w", sceAbstractStorageUnknown_kCX0k5t1v_w_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_3Cp_nOwl47U_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager6UpdateENS_11ServiceTypeE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("3Cp-nOwl47U", sceAbstractStorageUnknown_3Cp_nOwl47U_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_v9CSqw6Ve0w_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager9TerminateEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("v9CSqw6Ve0w", sceAbstractStorageUnknown_v9CSqw6Ve0w_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_KxTVuhlCL7o_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManagerC1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("KxTVuhlCL7o", sceAbstractStorageUnknown_KxTVuhlCL7o_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_YXXMdeJmxJw_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManagerC2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("YXXMdeJmxJw", sceAbstractStorageUnknown_YXXMdeJmxJw_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_2_S0J1RW2vQ_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManagerD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("2-S0J1RW2vQ", sceAbstractStorageUnknown_2_S0J1RW2vQ_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_K3qnBgQ0nC4_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManagerD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("K3qnBgQ0nC4", sceAbstractStorageUnknown_K3qnBgQ0nC4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_rHzXUC9OHh8_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransaction15SendHttpRequestERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEiRKSt3mapIS5_S5_St4lessIS5_ESaISt4pairIS6_S5_EEEmb() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("rHzXUC9OHh8", sceAbstractStorageUnknown_rHzXUC9OHh8_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_Dlri33kcH6o_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransaction4InitEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Dlri33kcH6o", sceAbstractStorageUnknown_Dlri33kcH6o_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_lH57wXDczHk_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransaction4TermEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("lH57wXDczHk", sceAbstractStorageUnknown_lH57wXDczHk_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_xJbY3QNYIzM_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransaction8SendDataEPKvm() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("xJbY3QNYIzM", sceAbstractStorageUnknown_xJbY3QNYIzM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_tbeA_hlRlHc_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransactionC1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("tbeA-hlRlHc", sceAbstractStorageUnknown_tbeA_hlRlHc_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_01BHTyfcbBs_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransactionC2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("01BHTyfcbBs", sceAbstractStorageUnknown_01BHTyfcbBs_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_1PrEoSKt3_w_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransactionD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("1PrEoSKt3-w", sceAbstractStorageUnknown_1PrEoSKt3_w_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_MoUJZiDoHMk_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransactionD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("MoUJZiDoHMk", sceAbstractStorageUnknown_MoUJZiDoHMk_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_I69kRgYrWmY_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item11GetPathNameEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("I69kRgYrWmY", sceAbstractStorageUnknown_I69kRgYrWmY_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_GCMRCWH3PU0_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item11SetMetadataEPN23sceMetadataReaderWriter8MetadataE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("GCMRCWH3PU0", sceAbstractStorageUnknown_GCMRCWH3PU0_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_SYb4Kmj0u88_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item13ParseMetadataEPN23sceMetadataReaderWriter8MetadataES3_() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("SYb4Kmj0u88", sceAbstractStorageUnknown_SYb4Kmj0u88_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_k2VonUL2gF8_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item14GetStorageNameEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("k2VonUL2gF8", sceAbstractStorageUnknown_k2VonUL2gF8_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_zkaNI1552m4_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item6RenameERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("zkaNI1552m4", sceAbstractStorageUnknown_zkaNI1552m4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_KAtGZCifCMo_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item7GetNameERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("KAtGZCifCMo", sceAbstractStorageUnknown_KAtGZCifCMo_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown__sxz_ThMtGM_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item7GetNameEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("-sxz-ThMtGM", sceAbstractStorageUnknown__sxz_ThMtGM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_wyEuZhFhbOE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item8set_metaERN23sceMetadataReaderWriter8MetadataERKSbIcSt11char_traitsIcENS_8StlAllocIcEEESA_() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("wyEuZhFhbOE", sceAbstractStorageUnknown_wyEuZhFhbOE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_F_Tz7UzYtJ4_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4Item8set_metaERN23sceMetadataReaderWriter8MetadataERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEm() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("F-Tz7UzYtJ4", sceAbstractStorageUnknown_F_Tz7UzYtJ4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_zC_hnmcVEOw_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemC2ERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("zC+hnmcVEOw", sceAbstractStorageUnknown_zC_hnmcVEOw_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_scYjSEuq2ik_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("scYjSEuq2ik", sceAbstractStorageUnknown_scYjSEuq2ik_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_QPNELEk9zkI_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("QPNELEk9zkI", sceAbstractStorageUnknown_QPNELEk9zkI_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_WnE1cxQELbY_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("WnE1cxQELbY", sceAbstractStorageUnknown_WnE1cxQELbY_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_Hg0GBcA80dk_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemdlEPv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Hg0GBcA80dk", sceAbstractStorageUnknown_Hg0GBcA80dk_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_gid_GlhKgJM_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemnwEm() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("gid+GlhKgJM", sceAbstractStorageUnknown_gid_GlhKgJM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_oJSXws_cIv8_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage6FolderC2ERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("oJSXws+cIv8", sceAbstractStorageUnknown_oJSXws_cIv8_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_GgNWVxe_YSU_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage6FolderD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("GgNWVxe-YSU", sceAbstractStorageUnknown_GgNWVxe_YSU_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown__1PWHzoXWyU_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage6FolderD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("-1PWHzoXWyU", sceAbstractStorageUnknown__1PWHzoXWyU_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_sLg6rUpiYSM_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage6FolderD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("sLg6rUpiYSM", sceAbstractStorageUnknown_sLg6rUpiYSM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_lYUGcgHYT7Y_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7AbsFreeEPv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("lYUGcgHYT7Y", sceAbstractStorageUnknown_lYUGcgHYT7Y_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_hQiPEotip7M_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Content12GetExtensionERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("hQiPEotip7M", sceAbstractStorageUnknown_hQiPEotip7M_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_pekT_IsAkQU_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Content12GetMimeTypesEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("pekT-IsAkQU", sceAbstractStorageUnknown_pekT_IsAkQU_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_xilbMn7q9qE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Content6RenameERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("xilbMn7q9qE", sceAbstractStorageUnknown_xilbMn7q9qE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_UZbuoykGKzE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7ContentC2ERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("UZbuoykGKzE", sceAbstractStorageUnknown_UZbuoykGKzE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_RenWwlxG9Tw_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7ContentD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("RenWwlxG9Tw", sceAbstractStorageUnknown_RenWwlxG9Tw_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_JZ3wKDjl0yQ_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7ContentD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("JZ3wKDjl0yQ", sceAbstractStorageUnknown_JZ3wKDjl0yQ_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_m7OSrfA7K_s_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7ContentD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("m7OSrfA7K+s", sceAbstractStorageUnknown_m7OSrfA7K_s_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_spsjzV2pTSc_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Service11NextStorageERSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("spsjzV2pTSc", sceAbstractStorageUnknown_spsjzV2pTSc_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_6Fp8jJ7A7CY_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Service13CreateStorageERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEPSt10shared_ptrINS_7StorageEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("6Fp8jJ7A7CY", sceAbstractStorageUnknown_6Fp8jJ7A7CY_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_wBaVZTLTjkg_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Service18clear_storage_listEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("wBaVZTLTjkg", sceAbstractStorageUnknown_wBaVZTLTjkg_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_DyerRilxWZ4_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Service4LoadENS_11ServiceTypeE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("DyerRilxWZ4", sceAbstractStorageUnknown_DyerRilxWZ4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_jCKhrVa9MEU_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Service4StopEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("jCKhrVa9MEU", sceAbstractStorageUnknown_jCKhrVa9MEU_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_tIIRbXa2ZOk_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Service5StartEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("tIIRbXa2ZOk", sceAbstractStorageUnknown_tIIRbXa2ZOk_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_vatp8UwS_nE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7Service6UnLoadEPS0_() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("vatp8UwS+nE", sceAbstractStorageUnknown_vatp8UwS_nE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_CrZTHC5yd64_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7ServiceC2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("CrZTHC5yd64", sceAbstractStorageUnknown_CrZTHC5yd64_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_IoNgvbVSw24_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7ServiceD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("IoNgvbVSw24", sceAbstractStorageUnknown_IoNgvbVSw24_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_PEuuRn6zhF4_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7ServiceD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("PEuuRn6zhF4", sceAbstractStorageUnknown_PEuuRn6zhF4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_Ngfl7wTF7M0_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7ServiceD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Ngfl7wTF7M0", sceAbstractStorageUnknown_Ngfl7wTF7M0_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_tLtIJWgGINI_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7StorageC2ERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("tLtIJWgGINI", sceAbstractStorageUnknown_tLtIJWgGINI_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_4ns7J9OrJ5g_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7StorageD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("4ns7J9OrJ5g", sceAbstractStorageUnknown_4ns7J9OrJ5g_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_aKBqHZKouts_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7StorageD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("aKBqHZKouts", sceAbstractStorageUnknown_aKBqHZKouts_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_fydJOJjDxX4_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage7StorageD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("fydJOJjDxX4", sceAbstractStorageUnknown_fydJOJjDxX4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_qtgEboQL0YE_nid_no_patch() {
|
||||
int APS5_VABI _ZN15AbstractStorage9AbsMallocEm() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("qtgEboQL0YE", sceAbstractStorageUnknown_qtgEboQL0YE_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_XBlKK5ijWI8_nid_no_patch() {
|
||||
int APS5_VABI _ZNK15AbstractStorage14MemfileContent10GetServiceEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("XBlKK5ijWI8", sceAbstractStorageUnknown_XBlKK5ijWI8_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_xP3aCoP48XI_nid_no_patch() {
|
||||
int APS5_VABI _ZNK15AbstractStorage14MemfileContent13GetCapabilityEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("xP3aCoP48XI", sceAbstractStorageUnknown_xP3aCoP48XI_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_FCSUVvY_0RM_nid_no_patch() {
|
||||
int APS5_VABI _ZNK15AbstractStorage14MemfileContent7GetStatEPNS_4StatE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("FCSUVvY-0RM", sceAbstractStorageUnknown_FCSUVvY_0RM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_oc6n6hdUrEM_nid_no_patch() {
|
||||
int APS5_VABI _ZNK15AbstractStorage4Item12GetThumbnailEPSt10shared_ptrINS_7ContentEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("oc6n6hdUrEM", sceAbstractStorageUnknown_oc6n6hdUrEM_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_Cb7xWd9_7tc_nid_no_patch() {
|
||||
int APS5_VABI _ZNK15AbstractStorage4Item15CreateThumbnailEPvPSt10shared_ptrINS_7ContentEE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("Cb7xWd9-7tc", sceAbstractStorageUnknown_Cb7xWd9_7tc_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_mv9rtQAknH4_nid_no_patch() {
|
||||
int APS5_VABI _ZNK15AbstractStorage6Folder7GetTypeEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("mv9rtQAknH4", sceAbstractStorageUnknown_mv9rtQAknH4_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_ka5TVf37Akg_nid_no_patch() {
|
||||
int APS5_VABI _ZNK15AbstractStorage7Content7GetTypeEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("ka5TVf37Akg", sceAbstractStorageUnknown_ka5TVf37Akg_nid_no_patch);
|
||||
|
||||
int APS5_VABI sceAbstractStorageUnknown_1uryzAWFUuA_nid_no_patch() {
|
||||
int APS5_VABI _ZNK15AbstractStorage7Storage7GetTypeEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("1uryzAWFUuA", sceAbstractStorageUnknown_1uryzAWFUuA_nid_no_patch);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include "SceTypes.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage12Serializable12readExternalESt10shared_ptrINS_7ContentEE();
|
||||
int APS5_VABI _ZN15AbstractStorage12Serializable13writeExternalESt10shared_ptrINS_7ContentEE();
|
||||
int APS5_VABI _ZN15AbstractStorage12SerializableC1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage12SerializableC2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage12SerializableD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage12SerializableD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent12readExternalESt10shared_ptrINS_7ContentEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent13writeExternalESt10shared_ptrINS_7ContentEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent14CreateInstanceESbIcSt11char_traitsIcENS_8StlAllocIcEEEN3paf6common9SharedPtrINS6_6BufferEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent14CreateInstanceESbIcSt11char_traitsIcENS_8StlAllocIcEEEPvm();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent4OpenEit();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent4ReadEPvlPl();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent5CloseEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent5FlushEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent5WriteEPKvlPl();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent6RemoveEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent8SeekByteEliPl();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContent8SeekTimeElPl();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentC1ESbIcSt11char_traitsIcENS_8StlAllocIcEEEN3paf6common9SharedPtrINS6_6BufferEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentC2ESbIcSt11char_traitsIcENS_8StlAllocIcEEEN3paf6common9SharedPtrINS6_6BufferEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14MemfileContentD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager10GetStorageERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEPSt10shared_ptrINS_7StorageEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager10InitializeEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager11GetInstanceERNS_12MemAllocatorEPv();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager11GetInstanceEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager12NotifyCreateERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEb();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager12NotifyRemoveERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEb();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager15ReleaseInstanceEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager16NotifyWriteCloseERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager16RegisterListenerEPNS_17ItemEventListenerE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager16RegisterListenerEPNS_20StorageEventListenerE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager16get_storage_nameERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager17NotifySetMetadataERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager18GetStorageNameListEPSt6vectorISbIcSt11char_traitsIcENS_8StlAllocIcEEESaIS6_EE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager18UnregisterListenerEPKNS_17ItemEventListenerE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager18UnregisterListenerEPKNS_20StorageEventListenerE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager20get_service_instanceENS_11ServiceTypeE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager21NotifyStorageAttachedERKSbIcSt11char_traitsIcENS_8StlAllocIcEEENS_11ServiceTypeE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager21NotifyStorageDetachedERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager4FreeEPv();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager4LoadENS_11ServiceTypeE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager6MallocEm();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager6UnloadENS_11ServiceTypeE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager6UpdateENS_11ServiceTypeE();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManager9TerminateEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManagerC1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManagerC2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManagerD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14StorageManagerD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransaction15SendHttpRequestERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEiRKSt3mapIS5_S5_St4lessIS5_ESaISt4pairIS6_S5_EEEmb();
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransaction4InitEv();
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransaction4TermEv();
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransaction8SendDataEPKvm();
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransactionC1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransactionC2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransactionD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage15HttpTransactionD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item11GetPathNameEv();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item11SetMetadataEPN23sceMetadataReaderWriter8MetadataE();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item13ParseMetadataEPN23sceMetadataReaderWriter8MetadataES3_();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item14GetStorageNameEv();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item6RenameERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item7GetNameERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item7GetNameEv();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item8set_metaERN23sceMetadataReaderWriter8MetadataERKSbIcSt11char_traitsIcENS_8StlAllocIcEEESA_();
|
||||
int APS5_VABI _ZN15AbstractStorage4Item8set_metaERN23sceMetadataReaderWriter8MetadataERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEm();
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemC2ERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemdlEPv();
|
||||
int APS5_VABI _ZN15AbstractStorage4ItemnwEm();
|
||||
int APS5_VABI _ZN15AbstractStorage6FolderC2ERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage6FolderD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage6FolderD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage6FolderD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7AbsFreeEPv();
|
||||
int APS5_VABI _ZN15AbstractStorage7Content12GetExtensionERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage7Content12GetMimeTypesEv();
|
||||
int APS5_VABI _ZN15AbstractStorage7Content6RenameERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage7ContentC2ERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage7ContentD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7ContentD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7ContentD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7Service11NextStorageERSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage7Service13CreateStorageERKSbIcSt11char_traitsIcENS_8StlAllocIcEEEPSt10shared_ptrINS_7StorageEE();
|
||||
int APS5_VABI _ZN15AbstractStorage7Service18clear_storage_listEv();
|
||||
int APS5_VABI _ZN15AbstractStorage7Service4LoadENS_11ServiceTypeE();
|
||||
int APS5_VABI _ZN15AbstractStorage7Service4StopEv();
|
||||
int APS5_VABI _ZN15AbstractStorage7Service5StartEv();
|
||||
int APS5_VABI _ZN15AbstractStorage7Service6UnLoadEPS0_();
|
||||
int APS5_VABI _ZN15AbstractStorage7ServiceC2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7ServiceD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7ServiceD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7ServiceD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7StorageC2ERKSbIcSt11char_traitsIcENS_8StlAllocIcEEE();
|
||||
int APS5_VABI _ZN15AbstractStorage7StorageD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7StorageD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage7StorageD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage9AbsMallocEm();
|
||||
int APS5_VABI _ZNK15AbstractStorage14MemfileContent10GetServiceEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage14MemfileContent13GetCapabilityEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage14MemfileContent7GetStatEPNS_4StatE();
|
||||
int APS5_VABI _ZNK15AbstractStorage4Item12GetThumbnailEPSt10shared_ptrINS_7ContentEE();
|
||||
int APS5_VABI _ZNK15AbstractStorage4Item15CreateThumbnailEPvPSt10shared_ptrINS_7ContentEE();
|
||||
int APS5_VABI _ZNK15AbstractStorage6Folder7GetTypeEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage7Content7GetTypeEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage7Storage7GetTypeEv();
|
||||
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include "prx/libSceAbstractStorage/include/Api.hpp"
|
||||
#include "prx/libSceAbstractStorage/include/InventoryExports.hpp"
|
||||
#include "prx/libSceAbstractStorage/include/LegacyExports.hpp"
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "prx/libSceAbstractYoutube/include/LegacyExports.hpp"
|
||||
#include "prx/libc/include/general/ExportMacros.hpp"
|
||||
#include "prx/libSceAbstractYoutube/include/InventoryExports.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include "SceTypes.hpp"
|
||||
@@ -92,3 +95,267 @@ int APS5_VABI sceAbstractYoutubeUnknown_vJGnqFj6ygE_nid_no_patch() {
|
||||
APS5_EXPORT("vJGnqFj6ygE", sceAbstractYoutubeUnknown_vJGnqFj6ygE_nid_no_patch);
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage13YoutubeFolder6RemoveEb() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage13YoutubeFolderD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage13YoutubeFolderD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage13YoutubeFolderD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent11SetMetadataEPN23sceMetadataReaderWriter8MetadataE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent13ParseMetadataEPN23sceMetadataReaderWriter8MetadataES3_() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent4OpenEit() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent4ReadEPvlPl() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent5CloseEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent5FlushEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent5WriteEPKvlPl() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent6RemoveEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent8SeekByteEliPl() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent8SeekTimeElPl() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContentD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContentD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContentD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeService13SearchStorageEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeService4StopEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeService5StartEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceC1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceC2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeStorage14GetStorageSizeEPlS1_S1_() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeStorageD0Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeStorageD1Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeStorageD2Ev() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage13YoutubeFolder10GetServiceEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage13YoutubeFolder13GetCapabilityEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage13YoutubeFolder7GetStatEPNS_4StatE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeContent10GetServiceEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeContent13GetCapabilityEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeContent7GetStatEPNS_4StatE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeService14GetServiceTypeEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeStorage10GetServiceEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeStorage13GetCapabilityEv() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeStorage7GetStatEPNS_4StatE() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown__plus_XiOtdILEHI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("+XiOtdILEHI", abstractYoutubeLegacyUnknown__plus_XiOtdILEHI_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_4orcGYZG2cE_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("4orcGYZG2cE", abstractYoutubeLegacyUnknown_4orcGYZG2cE_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_6svBaAI4Ggw_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("6svBaAI4Ggw", abstractYoutubeLegacyUnknown_6svBaAI4Ggw_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_CCv9CYanMNI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("CCv9CYanMNI", abstractYoutubeLegacyUnknown_CCv9CYanMNI_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_EEx55k0zSLo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("EEx55k0zSLo", abstractYoutubeLegacyUnknown_EEx55k0zSLo_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_HYDApQYDgcI_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("HYDApQYDgcI", abstractYoutubeLegacyUnknown_HYDApQYDgcI_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_IGnFlGNW_plus_Vo_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("IGnFlGNW+Vo", abstractYoutubeLegacyUnknown_IGnFlGNW_plus_Vo_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_JzBDUIC5xok_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("JzBDUIC5xok", abstractYoutubeLegacyUnknown_JzBDUIC5xok_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_NPYN89qO2Ks_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("NPYN89qO2Ks", abstractYoutubeLegacyUnknown_NPYN89qO2Ks_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_P_plus_ZjKSLi5lg_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("P+ZjKSLi5lg", abstractYoutubeLegacyUnknown_P_plus_ZjKSLi5lg_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_RkaqMMDQJp4_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("RkaqMMDQJp4", abstractYoutubeLegacyUnknown_RkaqMMDQJp4_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_ZpVRh3D86UY_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("ZpVRh3D86UY", abstractYoutubeLegacyUnknown_ZpVRh3D86UY_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_ZwkYXHwQ7Mc_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("ZwkYXHwQ7Mc", abstractYoutubeLegacyUnknown_ZwkYXHwQ7Mc_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_cktbTmca48I_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("cktbTmca48I", abstractYoutubeLegacyUnknown_cktbTmca48I_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_fUXj4GBxyHs_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("fUXj4GBxyHs", abstractYoutubeLegacyUnknown_fUXj4GBxyHs_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_g58APdyJ_minus_5Y_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("g58APdyJ-5Y", abstractYoutubeLegacyUnknown_g58APdyJ_minus_5Y_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_hXCJIJZZ5MY_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("hXCJIJZZ5MY", abstractYoutubeLegacyUnknown_hXCJIJZZ5MY_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_kgeuOe7oln8_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("kgeuOe7oln8", abstractYoutubeLegacyUnknown_kgeuOe7oln8_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_pR9ULw2VrSs_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("pR9ULw2VrSs", abstractYoutubeLegacyUnknown_pR9ULw2VrSs_nid_no_patch);
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_tjbj7QysZwk_nid_no_patch() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
APS5_EXPORT("tjbj7QysZwk", abstractYoutubeLegacyUnknown_tjbj7QysZwk_nid_no_patch);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "SceTypes.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI _ZN15AbstractStorage13YoutubeFolder6RemoveEb();
|
||||
int APS5_VABI _ZN15AbstractStorage13YoutubeFolderD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage13YoutubeFolderD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage13YoutubeFolderD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent11SetMetadataEPN23sceMetadataReaderWriter8MetadataE();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent13ParseMetadataEPN23sceMetadataReaderWriter8MetadataES3_();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent4OpenEit();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent4ReadEPvlPl();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent5CloseEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent5FlushEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent5WriteEPKvlPl();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent6RemoveEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent8SeekByteEliPl();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContent8SeekTimeElPl();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContentD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContentD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeContentD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeService13SearchStorageEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeService4StopEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeService5StartEv();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceC1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceC2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeServiceD2Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeStorage14GetStorageSizeEPlS1_S1_();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeStorageD0Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeStorageD1Ev();
|
||||
int APS5_VABI _ZN15AbstractStorage14YoutubeStorageD2Ev();
|
||||
int APS5_VABI _ZNK15AbstractStorage13YoutubeFolder10GetServiceEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage13YoutubeFolder13GetCapabilityEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage13YoutubeFolder7GetStatEPNS_4StatE();
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeContent10GetServiceEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeContent13GetCapabilityEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeContent7GetStatEPNS_4StatE();
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeService14GetServiceTypeEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeStorage10GetServiceEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeStorage13GetCapabilityEv();
|
||||
int APS5_VABI _ZNK15AbstractStorage14YoutubeStorage7GetStatEPNS_4StatE();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "SceTypes.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown__plus_XiOtdILEHI_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_4orcGYZG2cE_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_6svBaAI4Ggw_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_CCv9CYanMNI_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_EEx55k0zSLo_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_HYDApQYDgcI_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_IGnFlGNW_plus_Vo_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_JzBDUIC5xok_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_NPYN89qO2Ks_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_P_plus_ZjKSLi5lg_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_RkaqMMDQJp4_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_ZpVRh3D86UY_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_ZwkYXHwQ7Mc_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_cktbTmca48I_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_fUXj4GBxyHs_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_g58APdyJ_minus_5Y_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_hXCJIJZZ5MY_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_kgeuOe7oln8_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_pR9ULw2VrSs_nid_no_patch();
|
||||
int APS5_VABI abstractYoutubeLegacyUnknown_tjbj7QysZwk_nid_no_patch();
|
||||
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
#pragma once
|
||||
#include "prx/libSceAbstractYoutube/include/InventoryExports.hpp"
|
||||
#include "prx/libSceAbstractYoutube/include/LegacyExports.hpp"
|
||||
@@ -91,6 +91,19 @@ if(BUILD_TESTING)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_test_executable(agc_draw_setup_tests EXCLUDE_FROM_ALL tests/DrawSetup.cpp)
|
||||
target_include_directories(agc_draw_setup_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(agc_draw_setup_tests PRIVATE libSceAgc libc)
|
||||
configure_windows_unwind(agc_draw_setup_tests)
|
||||
if(BUILD_TESTING)
|
||||
set_target_properties(agc_draw_setup_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
|
||||
add_test(NAME agc_draw_setup COMMAND agc_draw_setup_tests)
|
||||
if(WIN32)
|
||||
set_tests_properties(agc_draw_setup PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_test_executable(agc_rewind_patch_tests EXCLUDE_FROM_ALL tests/RewindPatch.cpp)
|
||||
target_include_directories(agc_rewind_patch_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(agc_rewind_patch_tests PRIVATE libSceAgc libc)
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "prx/libSceAgc/Acb/include/Sync.hpp"
|
||||
#include "prx/libSceAgc/Command/include/Packet.hpp"
|
||||
#include "prx/libSceAgc/Command/include/Memory.hpp"
|
||||
#include "prx/libSceAgc/Acb/include/Memory.hpp"
|
||||
#include "prx/libSceAgc/DcbFlow/include/Memory.hpp"
|
||||
#include "prx/libSceAgc/Command/include/RegisterDefaults.hpp"
|
||||
#include "prx/libc/include/Shutdown.hpp"
|
||||
|
||||
@@ -835,6 +837,45 @@ void testAtomicGds() {
|
||||
}
|
||||
}
|
||||
|
||||
void testCopyDataAndComputeEvents() {
|
||||
Storage graphics;
|
||||
const auto* copy = sceAgcDcbCopyData(&graphics.buffer, 4, 1, 0x1122334450ull, 0xb, 2, 0x12345678u, 0, 1);
|
||||
const std::array<std::uint32_t, 6> graphicsExpected{0xc0044000u, 0x42104205u, 0x12345678u, 0, 0x22334450u, 0x11u};
|
||||
check(copy == graphics.words.data() && std::equal(graphicsExpected.begin(), graphicsExpected.end(), graphics.words.begin()), "graphics COPY_DATA packet mismatch");
|
||||
Storage wide;
|
||||
sceAgcDcbCopyData(&wide.buffer, 4, 0, 0x1000, 0xa, 0, 0x100000000ull, 1, 0);
|
||||
check(wide.words[1] == 0x00010205u && wide.words[2] == 0 && wide.words[3] == 1, "a 64-bit immediate COPY_DATA lost its high word");
|
||||
Storage compute;
|
||||
sceAgcAcbCopyData(&compute.buffer, 2, 0, 0x4000, 5, 0, 7, 0, 0);
|
||||
const std::array<std::uint32_t, 6> computeExpected{0xc0044000u, 0x205u, 7, 0, 0x4000u, 0};
|
||||
check(std::equal(computeExpected.begin(), computeExpected.end(), compute.words.begin()), "compute COPY_DATA packet mismatch");
|
||||
Storage rejected;
|
||||
rejected.words.fill(0xa5a5a5a5u);
|
||||
const auto rejectedWords = rejected.words;
|
||||
const auto* rejectedCursor = rejected.buffer.cursor_up;
|
||||
expectFailure([&] { sceAgcDcbCopyData(&rejected.buffer, 4, 4, 0x1000, 0xa, 0, 1, 0, 0); });
|
||||
check(rejected.words == rejectedWords && rejected.buffer.cursor_up == rejectedCursor, "a refused packet changed the command buffer");
|
||||
expectFailure([&] { sceAgcDcbCopyData(&rejected.buffer, 4, 0, 0x1000, 0xa, 4, 1, 0, 0); });
|
||||
check(rejected.words == rejectedWords && rejected.buffer.cursor_up == rejectedCursor, "a refused packet changed the command buffer");
|
||||
expectFailure([&] { sceAgcAcbCopyData(&rejected.buffer, 2, 0, 0x4000, 5, 0, 1, 2, 0); });
|
||||
check(rejected.words == rejectedWords && rejected.buffer.cursor_up == rejectedCursor, "a refused packet changed the command buffer");
|
||||
expectFailure([&] { sceAgcAcbCopyData(&rejected.buffer, 2, 0, 0x4000, 5, 0, 1, 0, 2); });
|
||||
check(rejected.words == rejectedWords && rejected.buffer.cursor_up == rejectedCursor, "a refused packet changed the command buffer");
|
||||
check(sceAgcDcbCopyDataGetSize() == 24 && sceAgcAcbCopyDataGetSize() == 24, "COPY_DATA packet sizes");
|
||||
Storage events;
|
||||
sceAgcAcbEventWrite(&events.buffer, 7, nullptr);
|
||||
sceAgcAcbEventWrite(&events.buffer, 0x16, nullptr);
|
||||
const std::array<std::uint32_t, 4> eventsExpected{0xc0004600u, 0x407u, 0xc0004600u, 0x16u};
|
||||
check(std::equal(eventsExpected.begin(), eventsExpected.end(), events.words.begin()), "compute EVENT_WRITE packet mismatch");
|
||||
Storage refused;
|
||||
refused.words.fill(0xa5a5a5a5u);
|
||||
const auto refusedWords = refused.words;
|
||||
const auto* refusedCursor = refused.buffer.cursor_up;
|
||||
expectFailure([&] { sceAgcAcbEventWrite(&refused.buffer, 0x40, nullptr); });
|
||||
check(refused.words == refusedWords && refused.buffer.cursor_up == refusedCursor, "a refused packet changed the command buffer");
|
||||
check(sceAgcAcbEventWriteGetSize(7) == 8, "compute EVENT_WRITE packet size");
|
||||
}
|
||||
|
||||
void testDebugRaiseException() {
|
||||
int result = -1;
|
||||
try {
|
||||
@@ -1080,6 +1121,7 @@ int main(int argc, char** argv) {
|
||||
testEndOfPipePatches();
|
||||
testAtomicGds();
|
||||
testDebugRaiseException();
|
||||
testCopyDataAndComputeEvents();
|
||||
testDefaults();
|
||||
testDefaultsTypes();
|
||||
LibcRunShutdown_nid_postfix();
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "prx/libSceAgc/Command/include/Packet.hpp"
|
||||
#include "prx/libSceAgc/DcbDraw/include/DrawIndexed.hpp"
|
||||
#include "prx/libSceAgc/DcbDraw/include/DrawNonIndexed.hpp"
|
||||
#include "prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp"
|
||||
#include "prx/libSceAgc/DcbDraw/include/Instancing.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
|
||||
struct Storage {
|
||||
std::array<std::uint32_t, 64> words{};
|
||||
CommandBuffer buffer{words.data(), words.data() + words.size(), words.data(), words.data() + words.size(), nullptr, nullptr, 0};
|
||||
};
|
||||
|
||||
void check(bool condition, const char* message) {
|
||||
if (!condition) throw std::runtime_error(message);
|
||||
}
|
||||
|
||||
template <typename TAction>
|
||||
void expectFailure(Storage& storage, TAction action, const char* message) {
|
||||
const auto before = storage.words;
|
||||
const auto* cursor = storage.buffer.cursor_up;
|
||||
try {
|
||||
action();
|
||||
} catch (const std::runtime_error&) {
|
||||
check(storage.words == before && storage.buffer.cursor_up == cursor, message);
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
void expectPacket(const Storage& storage, const std::uint32_t* packet, const std::uint32_t* start, const std::array<std::uint32_t, N>& expected, std::uint32_t size, const char* message) {
|
||||
check(packet == start && std::equal(expected.begin(), expected.end(), packet), message);
|
||||
check(storage.buffer.cursor_up == start + N, message);
|
||||
check(size == N * sizeof(std::uint32_t), message);
|
||||
}
|
||||
|
||||
void testNumInstances() {
|
||||
Storage storage;
|
||||
const auto* packet = sceAgcDcbSetNumInstances(&storage.buffer, 7);
|
||||
expectPacket(storage, packet, storage.words.data(), std::array<std::uint32_t, 2>{0xc0002f00u, 7}, sceAgcDcbSetNumInstancesGetSize(), "NUM_INSTANCES packet mismatch");
|
||||
}
|
||||
|
||||
void testIndexSize() {
|
||||
Storage storage;
|
||||
const auto* packet = sceAgcDcbSetIndexSize(&storage.buffer, 1, 2);
|
||||
expectPacket(storage, packet, storage.words.data(), std::array<std::uint32_t, 3>{0xc0017a00u, 0x20000243u, 0x481u}, sceAgcDcbSetIndexSizeGetSize(), "index size packet mismatch");
|
||||
const auto* objectId = sceAgcDcbSetIndexSize_0600(&storage.buffer, 2, 3, 1);
|
||||
check(objectId == storage.words.data() + 3 && objectId[0] == 0xc0017a00u && objectId[1] == 0x20000243u && objectId[2] == (0x4c2u | 0x4000u), "index size packet with a per-instance object id mismatch");
|
||||
expectFailure(storage, [&] { sceAgcDcbSetIndexSize(&storage.buffer, 3, 0); }, "an index size above 2 was accepted");
|
||||
expectFailure(storage, [&] { sceAgcDcbSetIndexSize(&storage.buffer, 0, 4); }, "a cache policy above 3 was accepted");
|
||||
expectFailure(storage, [&] { sceAgcDcbSetIndexSize_0600(&storage.buffer, 0, 0, 2); }, "a per-instance object id above 1 was accepted");
|
||||
}
|
||||
|
||||
void testDrawIndexOffset() {
|
||||
Storage storage;
|
||||
const auto* packet = sceAgcDcbDrawIndexOffset(&storage.buffer, 12, 36, 0);
|
||||
expectPacket(storage, packet, storage.words.data(), std::array<std::uint32_t, 5>{0xc0033500u, 36, 12, 36, 0}, sceAgcDcbDrawIndexOffsetGetSize(), "DRAW_INDEX_OFFSET_2 packet mismatch");
|
||||
const auto* empty = sceAgcDcbDrawIndexOffset(&storage.buffer, 0, 0, 0);
|
||||
check(empty == storage.words.data() + 5 && empty[1] == 1 && empty[3] == 0, "an empty indexed offset draw did not keep a maximum size of one");
|
||||
}
|
||||
|
||||
void testDrawIndirect() {
|
||||
Storage storage;
|
||||
const auto* packet = sceAgcDcbDrawIndirect(&storage.buffer, 0x40, 0);
|
||||
expectPacket(storage, packet, storage.words.data(), std::array<std::uint32_t, 5>{0xc0032400u, 0x40, 0x280, 0x280, 2}, sceAgcDcbDrawIndirectGetSize(), "DRAW_INDIRECT packet mismatch");
|
||||
expectFailure(storage, [&] { sceAgcDcbDrawIndirect(&storage.buffer, 2, 0); }, "a misaligned indirect argument offset was accepted");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
testNumInstances();
|
||||
testIndexSize();
|
||||
testDrawIndexOffset();
|
||||
testDrawIndirect();
|
||||
} catch (const std::exception& error) {
|
||||
std::fprintf(stderr, "%s\n", error.what());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,24 @@
|
||||
if(BUILD_TESTING)
|
||||
add_test_executable(agc_preparation_inputs_tests
|
||||
tests/PreparationInputs.cpp
|
||||
Execution/src/Driver/Shaders/ShaderDiagnostics.cpp
|
||||
${CMAKE_SOURCE_DIR}/core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp)
|
||||
target_include_directories(agc_preparation_inputs_tests PRIVATE
|
||||
${LIBS_INCLUDE_DIR}
|
||||
$<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
|
||||
target_link_libraries(agc_preparation_inputs_tests PRIVATE libc)
|
||||
configure_windows_unwind(agc_preparation_inputs_tests)
|
||||
foreach(mode enabled disabled selected failure concurrent write-failure capture-write-failure)
|
||||
add_test(NAME agc_preparation_inputs_${mode} COMMAND agc_preparation_inputs_tests ${mode})
|
||||
set_tests_properties(agc_preparation_inputs_${mode} PROPERTIES TIMEOUT 20)
|
||||
if(WIN32)
|
||||
set_tests_properties(agc_preparation_inputs_${mode} PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
function(ensure_agc_glslang)
|
||||
if(TARGET glslang AND TARGET SPIRV AND TARGET glslang-standalone)
|
||||
return()
|
||||
@@ -31,6 +52,16 @@ endfunction()
|
||||
|
||||
ensure_agc_glslang()
|
||||
|
||||
if(BUILD_TESTING AND WIN32)
|
||||
add_test_executable(agc_process_sampler_stack_tests tests/ProcessSamplerStack.cpp Execution/src/WorkerSampler.cpp)
|
||||
target_include_directories(agc_process_sampler_stack_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(agc_process_sampler_stack_tests PRIVATE libc)
|
||||
configure_windows_unwind(agc_process_sampler_stack_tests)
|
||||
add_test(NAME agc_process_sampler_stack COMMAND agc_process_sampler_stack_tests)
|
||||
set_tests_properties(agc_process_sampler_stack PROPERTIES TIMEOUT 20 ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
|
||||
endif()
|
||||
|
||||
set(agcTextureDetileShaderSource ${CMAKE_CURRENT_SOURCE_DIR}/Graphics/shaders/TextureDetile.comp)
|
||||
set(agcTextureDetileGeneratedRoot ${CMAKE_CURRENT_BINARY_DIR}/generated)
|
||||
set(agcTextureDetileGeneratedDir ${agcTextureDetileGeneratedRoot}/prx/libSceAgcDriver/Graphics/shaders)
|
||||
@@ -56,6 +87,28 @@ add_custom_command(
|
||||
DEPENDS "${agcTextureDetileShaderSource}" glslang-standalone
|
||||
VERBATIM
|
||||
)
|
||||
set(agcTextureDetileWordsShaderSpv ${agcTextureDetileGeneratedDir}/TextureDetileWords.spv)
|
||||
set(agcTextureDetileWordsShaderHeader ${agcTextureDetileGeneratedDir}/TextureDetileWords_spv.h)
|
||||
add_custom_command(
|
||||
OUTPUT "${agcTextureDetileWordsShaderHeader}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${agcTextureDetileGeneratedDir}"
|
||||
COMMAND "$<TARGET_FILE:glslang-standalone>" -V --target-env vulkan1.1 -DWORD_GROUPS=1 -o "${agcTextureDetileWordsShaderSpv}" "${agcTextureDetileShaderSource}"
|
||||
COMMAND ${CMAKE_COMMAND} -DINPUT=${agcTextureDetileWordsShaderSpv} -DOUTPUT=${agcTextureDetileWordsShaderHeader}
|
||||
-DSYMBOL=TEXTURE_DETILE_WORDS_SPV -P "${CMAKE_CURRENT_SOURCE_DIR}/embed_spirv.cmake"
|
||||
DEPENDS "${agcTextureDetileShaderSource}" glslang-standalone
|
||||
VERBATIM
|
||||
)
|
||||
set(agcTextureDetileImageWordsShaderSpv ${agcTextureDetileGeneratedDir}/TextureDetileImageWords.spv)
|
||||
set(agcTextureDetileImageWordsShaderHeader ${agcTextureDetileGeneratedDir}/TextureDetileImageWords_spv.h)
|
||||
add_custom_command(
|
||||
OUTPUT "${agcTextureDetileImageWordsShaderHeader}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${agcTextureDetileGeneratedDir}"
|
||||
COMMAND "$<TARGET_FILE:glslang-standalone>" -V --target-env vulkan1.1 -DLINEAR_IMAGE=1 -DWORD_GROUPS=1 -o "${agcTextureDetileImageWordsShaderSpv}" "${agcTextureDetileShaderSource}"
|
||||
COMMAND ${CMAKE_COMMAND} -DINPUT=${agcTextureDetileImageWordsShaderSpv} -DOUTPUT=${agcTextureDetileImageWordsShaderHeader}
|
||||
-DSYMBOL=TEXTURE_DETILE_IMAGE_WORDS_SPV -P "${CMAKE_CURRENT_SOURCE_DIR}/embed_spirv.cmake"
|
||||
DEPENDS "${agcTextureDetileShaderSource}" glslang-standalone
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
set(agcMeshArgumentsShaderSource ${CMAKE_CURRENT_SOURCE_DIR}/Graphics/shaders/MeshArguments.comp)
|
||||
foreach(agcReadbackKind IN ITEMS Uint Depth)
|
||||
@@ -103,6 +156,19 @@ add_custom_command(
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
set(agcStagingCopyBackShaderSource ${CMAKE_CURRENT_SOURCE_DIR}/Graphics/shaders/StagingCopyBack.comp)
|
||||
set(agcStagingCopyBackShaderSpv ${agcTextureDetileGeneratedDir}/StagingCopyBack.spv)
|
||||
set(agcStagingCopyBackShaderHeader ${agcTextureDetileGeneratedDir}/StagingCopyBack_spv.h)
|
||||
add_custom_command(
|
||||
OUTPUT "${agcStagingCopyBackShaderHeader}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${agcTextureDetileGeneratedDir}"
|
||||
COMMAND "$<TARGET_FILE:glslang-standalone>" -V --target-env vulkan1.1 -o "${agcStagingCopyBackShaderSpv}" "${agcStagingCopyBackShaderSource}"
|
||||
COMMAND ${CMAKE_COMMAND} -DINPUT=${agcStagingCopyBackShaderSpv} -DOUTPUT=${agcStagingCopyBackShaderHeader}
|
||||
-DSYMBOL=STAGING_COPY_BACK_SPV -P "${CMAKE_CURRENT_SOURCE_DIR}/embed_spirv.cmake"
|
||||
DEPENDS "${agcStagingCopyBackShaderSource}" glslang-standalone
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
set(agcCmaskClearShaderSource ${CMAKE_CURRENT_SOURCE_DIR}/Graphics/shaders/CmaskClear.comp)
|
||||
set(agcCmaskClearShaderSpv ${agcTextureDetileGeneratedDir}/CmaskClear.spv)
|
||||
set(agcCmaskClearShaderHeader ${agcTextureDetileGeneratedDir}/CmaskClear_spv.h)
|
||||
@@ -167,6 +233,23 @@ add_custom_command(
|
||||
DEPENDS "${agcSampleDumpsShaderSource}" glslang-standalone
|
||||
VERBATIM
|
||||
)
|
||||
function(agc_embedded_shader SOURCE STEM SYMBOL OUT_LIST)
|
||||
set(source "${CMAKE_CURRENT_SOURCE_DIR}/Graphics/shaders/${SOURCE}")
|
||||
set(spv "${agcTextureDetileGeneratedDir}/${STEM}.spv")
|
||||
set(header "${agcTextureDetileGeneratedDir}/${STEM}_spv.h")
|
||||
add_custom_command(
|
||||
OUTPUT "${header}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${agcTextureDetileGeneratedDir}"
|
||||
COMMAND "$<TARGET_FILE:glslang-standalone>" -V --target-env vulkan1.1 -o "${spv}" "${source}"
|
||||
COMMAND ${CMAKE_COMMAND} -DINPUT=${spv} -DOUTPUT=${header}
|
||||
-DSYMBOL=${SYMBOL} -P "${CMAKE_CURRENT_SOURCE_DIR}/embed_spirv.cmake"
|
||||
DEPENDS "${source}" glslang-standalone
|
||||
VERBATIM
|
||||
)
|
||||
set(${OUT_LIST} ${${OUT_LIST}} "${header}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
set(agcDepthTransferShaderHeaders)
|
||||
agc_embedded_shader(DepthToStorage.comp DepthToStorage DEPTH_TO_STORAGE_SPV agcDepthTransferShaderHeaders)
|
||||
foreach(agcPresentationStage IN ITEMS Vert Frag)
|
||||
string(TOLOWER "${agcPresentationStage}" agcPresentationExtension)
|
||||
string(TOUPPER "${agcPresentationStage}" agcPresentationSymbol)
|
||||
@@ -372,12 +455,16 @@ set(agcDriverSources
|
||||
${agcMultisampleUploadHeader}
|
||||
${agcCmaskClearShaderHeader}
|
||||
${agcMeshArgumentsShaderHeader}
|
||||
${agcStagingCopyBackShaderHeader}
|
||||
${agcTextureDetileImageShaderHeader}
|
||||
${agcTextureRepackShaderHeader}
|
||||
${agcDispatchArgumentsShaderHeader}
|
||||
${agcTextureDetileWordsShaderHeader}
|
||||
${agcTextureDetileImageWordsShaderHeader}
|
||||
${agcSampleCounterShaderHeader}
|
||||
${agcSampleDumpsShaderHeader}
|
||||
${agcPresentationShaderHeaders}
|
||||
${agcDepthTransferShaderHeaders}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Eq/src/Event.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Eq/src/Query.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Resource/src/Lifecycle.cpp
|
||||
@@ -426,6 +513,10 @@ add_shader_recompiler(shader_recompiler_agc_driver libc
|
||||
${agcShaderCacheGuardSources}
|
||||
)
|
||||
|
||||
target_include_directories(libSceAgcDriver INTERFACE
|
||||
$<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
|
||||
target_link_libraries(libSceAgcDriver PRIVATE
|
||||
shader_recompiler_agc_driver
|
||||
decoder_png
|
||||
@@ -665,12 +756,14 @@ foreach(agcTestFragment IN LISTS agcTestFragments)
|
||||
include(${agcTestFragment})
|
||||
endforeach()
|
||||
|
||||
target_include_directories(agc_driver_gcn_compare_exec_writes_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
set_tests_properties(agc_driver_msaa_dcc_state ${multisampledDccClearTests} PROPERTIES
|
||||
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" TIMEOUT 30 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
|
||||
set_tests_properties(${multisampledDccClearTests} PROPERTIES SKIP_RETURN_CODE 77)
|
||||
if(WIN32)
|
||||
set_tests_properties(agc_driver_dithered_alpha_to_coverage agc_driver_two_sample_dithered_alpha_to_coverage ${multisampledDccClearTests} PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
set_tests_properties(agc_driver_dithered_alpha_to_coverage agc_driver_two_sample_dithered_alpha_to_coverage agc_driver_alpha_to_coverage_sample_mask_export agc_driver_two_sample_alpha_to_coverage_sample_mask_export ${multisampledDccClearTests} PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
|
||||
endif()
|
||||
endif()
|
||||
@@ -734,7 +827,7 @@ if(BUILD_TESTING)
|
||||
BUILD_WITH_INSTALL_RPATH TRUE INSTALL_RPATH "$ORIGIN")
|
||||
endif()
|
||||
|
||||
foreach(partialStoreTest agc_driver_depth_plane_partial_store_unimported agc_driver_depth_plane_partial_store_buffer_copy)
|
||||
foreach(partialStoreTest agc_driver_depth_plane_partial_store_unimported agc_driver_depth_plane_partial_store_image_copy agc_driver_depth_plane_partial_store_buffer_copy)
|
||||
set_tests_properties(${partialStoreTest} PROPERTIES
|
||||
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_NO_HOST_IMPORT=1" TIMEOUT 30 SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
|
||||
if(WIN32)
|
||||
@@ -901,6 +994,22 @@ target_link_libraries(agc_compute_pipeline_replay PRIVATE libSceAgcDriver libc)
|
||||
set_target_properties(agc_compute_pipeline_replay PROPERTIES CXX_EXTENSIONS OFF)
|
||||
configure_windows_unwind(agc_compute_pipeline_replay)
|
||||
|
||||
add_library(agc_oracle_support STATIC tools/OracleCodeObject.cpp tools/OracleDispatch.cpp)
|
||||
target_include_directories(agc_oracle_support PUBLIC
|
||||
${LIBS_INCLUDE_DIR}
|
||||
$<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
${CMAKE_SOURCE_DIR}/core/shader/recompiler
|
||||
${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR}
|
||||
${ANYPS5_SPIRV_HEADERS_INCLUDE_DIR}
|
||||
)
|
||||
target_link_libraries(agc_oracle_support PUBLIC libSceAgcDriver libc)
|
||||
set_target_properties(agc_oracle_support PROPERTIES CXX_EXTENSIONS OFF)
|
||||
|
||||
add_executable(agc_oracle_runner EXCLUDE_FROM_ALL tools/OracleRunner.cpp)
|
||||
target_link_libraries(agc_oracle_runner PRIVATE agc_oracle_support)
|
||||
set_target_properties(agc_oracle_runner PROPERTIES CXX_EXTENSIONS OFF)
|
||||
configure_windows_unwind(agc_oracle_runner)
|
||||
|
||||
if(BUILD_TESTING AND ANYPS5_ENABLE_SPIRV_TOOLS)
|
||||
add_test(NAME agc_compute_pipeline_inspection COMMAND ${CMAKE_COMMAND}
|
||||
-DREPLAY=$<TARGET_FILE:agc_compute_pipeline_replay>
|
||||
|
||||
@@ -54,13 +54,14 @@ int AddEvent(KernelEqueue eq, std::uint32_t queue, std::uintptr_t ident, void* u
|
||||
}
|
||||
|
||||
int DeleteEvent(KernelEqueue eq, std::uintptr_t ident, const char* caller) {
|
||||
{
|
||||
std::lock_guard lock(g_mutex);
|
||||
std::erase_if(g_registrations, [&](const Registration& r) { return r.eq == eq && r.ident == ident; });
|
||||
if (eq == 0 || !EqueuePin_nid_postfix(eq)) {
|
||||
throw std::runtime_error(std::string(caller) + ": invalid event queue");
|
||||
}
|
||||
if (EqueueDeleteEvent_nid_postfix(eq, ident, EvfiltGraphicsCore) != EQUEUE_OK) {
|
||||
throw std::runtime_error(std::string(caller) + ": event is not registered");
|
||||
}
|
||||
std::lock_guard lock(g_mutex);
|
||||
std::erase_if(g_registrations, [&](const Registration& r) { return r.eq == eq && r.ident == ident; });
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -85,10 +86,16 @@ bool AgcDriverDeliverEopInterrupt(std::uint32_t queue) {
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI sceAgcDriverAddEqEvent(KernelEqueue eq, int id, void* udata) {
|
||||
if (id < 0) {
|
||||
throw std::runtime_error(std::string(__func__) + ": negative event id");
|
||||
}
|
||||
return AddEvent(eq, static_cast<std::uint32_t>(id), static_cast<std::uintptr_t>(id), udata, __func__);
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcDriverDeleteEqEvent(KernelEqueue eq, int id) {
|
||||
if (id < 0) {
|
||||
throw std::runtime_error(std::string(__func__) + ": negative event id");
|
||||
}
|
||||
return DeleteEvent(eq, static_cast<std::uintptr_t>(id), __func__);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Shaders/ShaderRegistry.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Recipe.hpp"
|
||||
#include "prx/libc/include/GuestAllocations.hpp"
|
||||
#include "IntermediateRepresentation/IrMetadata/ResourcePlan.hpp"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
@@ -15,12 +17,34 @@
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "prx/libc/include/general/AtomicSharedPtr.hpp"
|
||||
|
||||
namespace AgcDriver::DriverDetail {
|
||||
|
||||
inline bool CaptureRegisteredViewsCurrent(std::span<const ShaderRecompiler::RegisteredImageView> views) {
|
||||
if (views.empty()) return true;
|
||||
for (std::uint32_t attempt = 0; attempt < 2u; ++attempt) {
|
||||
const auto before = GuestAllocations::GuestAllocationsGeneration_nid_postfix();
|
||||
bool current = true;
|
||||
for (const auto& view : views) {
|
||||
const auto range = GuestAllocations::GuestAllocationsLookup_nid_postfix(static_cast<std::uintptr_t>(view.address), false);
|
||||
if (view.hasRange != (range != nullptr)) {
|
||||
current = false;
|
||||
break;
|
||||
}
|
||||
if (range != nullptr && (range->address != view.rangeAddress || range->bytes != view.rangeBytes || range->allocationAddress != view.allocationAddress || range->allocationBytes != view.allocationBytes || range->backingSerial != view.backingSerial || range->readable != view.readable || range->writable != view.writable || range->gpu != view.gpu)) {
|
||||
current = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (before == GuestAllocations::GuestAllocationsGeneration_nid_postfix()) return current;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline constexpr std::size_t MaxDispatchVariants = 8;
|
||||
|
||||
struct DispatchVariant {
|
||||
@@ -30,6 +54,7 @@ struct DispatchVariant {
|
||||
std::vector<SharedWords> shared;
|
||||
std::uint64_t forgetSerial = 0;
|
||||
std::shared_ptr<const ShaderRecompiler::RecompileResult> compiled;
|
||||
std::shared_ptr<const std::vector<ShaderRecompiler::RegisteredImageView>> registeredViews;
|
||||
std::array<std::uint32_t, 4> meshIndexDescriptor{};
|
||||
|
||||
std::shared_ptr<const ShaderSnapshot> shader;
|
||||
|
||||
@@ -124,6 +124,7 @@ enum class DrawVerdict { Drawn, Nothing, Rejected };
|
||||
struct StageCapture {
|
||||
std::shared_ptr<const ShaderRecompiler::RecompileResult> compiled;
|
||||
std::shared_ptr<const ShaderRecompiler::ResourceCapture> capture;
|
||||
std::shared_ptr<const std::vector<ShaderRecompiler::RegisteredImageView>> registeredViews;
|
||||
std::vector<ShaderRecompiler::MemoryRegion> regions;
|
||||
std::vector<std::shared_ptr<const ShaderRecompiler::SrtGuestWords>> supplied;
|
||||
std::uint64_t forgetSerial = 0;
|
||||
|
||||
@@ -184,6 +184,7 @@ struct PreparedShaders : PreparedShaderState {
|
||||
std::atomic<bool> demanded{false};
|
||||
bool pending = false;
|
||||
std::vector<std::size_t> convertedSamples;
|
||||
std::vector<std::size_t> layerRowSamples;
|
||||
};
|
||||
|
||||
class SharedCode {
|
||||
@@ -302,7 +303,7 @@ struct ShaderSnapshot {
|
||||
};
|
||||
|
||||
|
||||
std::shared_ptr<const ShaderSnapshot> ReadRawShader(std::uint64_t address);
|
||||
std::shared_ptr<const ShaderSnapshot> ReadRawShader(std::uint64_t address, const std::shared_ptr<const ShaderSnapshot>& retained = {});
|
||||
std::shared_ptr<const ShaderSnapshot> ReadUserDataTailContinuation(std::span<const std::uint32_t> code, std::uint32_t userDataBase, std::span<const std::uint32_t> userData);
|
||||
std::shared_ptr<const ShaderSnapshot> ProgramSnapshot(const ShaderRegistry& shaders, std::uint64_t address, std::initializer_list<std::uint8_t> types);
|
||||
void NoteRawGraphicsDraw(const ShaderSnapshot& snapshot);
|
||||
|
||||
@@ -9,6 +9,10 @@ inline bool FragmentShaderBarycentricUsable(VkDriverId driver, bool reported) {
|
||||
return reported && driver != VK_DRIVER_ID_MOLTENVK;
|
||||
}
|
||||
|
||||
inline bool HostInterpolationPreferred(VkDriverId driver) {
|
||||
return driver == VK_DRIVER_ID_MESA_RADV;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -54,6 +54,7 @@ void Write(std::uint64_t address, std::span<const std::byte> source, std::size_t
|
||||
void WriteChanged(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original);
|
||||
void WriteChanged(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original, std::uint32_t byteStoreLimit);
|
||||
std::uint32_t ChangedByteStoreLimit();
|
||||
void WriteChangedKeepingGuest(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original);
|
||||
|
||||
// Write tracking. The guest arena is reserved with page write watching, so CollectWrites learns which
|
||||
// pages of a range the CPU wrote since they were last collected, stamps their 64 KiB blocks with a new
|
||||
@@ -126,6 +127,7 @@ std::uint64_t CollectWritesUncached(std::uint64_t address, std::size_t bytes);
|
||||
// tracker mutex, so every collect that bumped before it has finished its walk and every later
|
||||
// collect stamps newer.
|
||||
std::uint64_t TrackerGeneration();
|
||||
void AdvanceTrackerGenerationForTest(std::uint64_t generation);
|
||||
std::uint64_t NewestStamp(std::uint64_t address, std::size_t bytes);
|
||||
std::uint64_t UntrackedHint(std::uint64_t address, std::size_t bytes);
|
||||
// Whether no CPU write touched the range since `generation`: an uncached resetting collect of the
|
||||
|
||||
@@ -51,6 +51,8 @@ struct KeyboardGlyphEntry {
|
||||
};
|
||||
|
||||
inline constexpr char32_t KeyboardFallbackCode = 0xFFFD;
|
||||
inline constexpr std::uint8_t KeyboardCompositionMark = 1;
|
||||
inline constexpr std::uint8_t KeyboardSelectionMark = 2;
|
||||
|
||||
std::span<const KeyboardGlyphEntry> KeyboardGlyphTable();
|
||||
bool KeyboardHasGlyph(char32_t code);
|
||||
|
||||
@@ -14,6 +14,11 @@ namespace AgcDriver::Pm4 {
|
||||
|
||||
constexpr std::size_t GdsBytes = 0x10000;
|
||||
std::uint64_t GdsAddress();
|
||||
void RequestImportableGds(bool requested);
|
||||
bool ImportableGdsRequested();
|
||||
bool GdsShared();
|
||||
bool GdsImportable();
|
||||
void RejectGdsImport();
|
||||
|
||||
struct DrawParameters {
|
||||
std::uint64_t indexAddress;
|
||||
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
|
||||
private:
|
||||
std::shared_ptr<const ShaderRecompiler::ResourceCapture> capture(const ShaderRecompiler::RecompileRequest& request, const ShaderRecompiler::SourceHandle* handle, const ShaderRecompiler::PreparedShaderInvocation* invocation);
|
||||
std::shared_ptr<const ShaderRecompiler::ResourceCapture> captureWaitingOnFailure(const ShaderRecompiler::RecompileRequest& request, const ShaderRecompiler::SourceHandle* handle, const ShaderRecompiler::PreparedShaderInvocation* invocation);
|
||||
static constexpr std::size_t PageBytes = 4096;
|
||||
static constexpr std::size_t PageWords = PageBytes / sizeof(std::uint32_t);
|
||||
|
||||
@@ -169,6 +170,8 @@ private:
|
||||
std::size_t descriptorSpanBytes = 0;
|
||||
std::uint64_t rawInvalidations = 0;
|
||||
std::uint32_t forceSync = 0;
|
||||
std::uint64_t branchReadsRefused = 0;
|
||||
bool waitBranches = false;
|
||||
};
|
||||
|
||||
// The positions, among a dispatch-cache variant's stored words, of the pure flat-SRT leaves a
|
||||
|
||||
@@ -301,19 +301,19 @@ public:
|
||||
// records. Null when nothing is prepared: the resource cache may serve the dispatch (its
|
||||
// Revalidate stays under the mutex), or APS5_LOCKED_BUILD=1 keeps the whole build under it as
|
||||
// before. `shader` and `snapshots` must outlive the dispatch.
|
||||
std::shared_ptr<PreparedDispatch> PrepareDispatch(const ShaderRecompiler::RecompileResult& shader, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t dispatchThreads = 0, std::uint64_t programAddress = 0, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear = std::nullopt);
|
||||
std::shared_ptr<PreparedDispatch> PrepareDispatch(const ShaderRecompiler::RecompileResult& shader, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t dispatchThreads = 0, std::uint64_t programAddress = 0, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear = std::nullopt, const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews = nullptr);
|
||||
// APS5_PROFILE_DRAW: the parts of a PrepareDispatch in milliseconds, in the order key, find,
|
||||
// precollect, presync, stage A (the driver's 'prepare:' rows).
|
||||
static std::span<const double, 5> PreparePhaseMs(const PreparedDispatch& prepared);
|
||||
// `recipe`, when given, receives the Recipe a successful call built for its dispatch-cache
|
||||
// variant (design_cpu_final M4): only when the resource cache served or took the object
|
||||
// (reusable, cacheable) and recipes are on (APS5_NO_DISPATCH_RECIPE=1 builds none); else null.
|
||||
void Dispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::span<const Graphics::GuestMemorySnapshot> snapshots = {}, std::uint64_t programAddress = 0, std::shared_ptr<PreparedDispatch> prepared = nullptr, std::shared_ptr<const Recipe>* recipe = nullptr, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear = std::nullopt);
|
||||
void Dispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::span<const Graphics::GuestMemorySnapshot> snapshots = {}, std::uint64_t programAddress = 0, std::shared_ptr<PreparedDispatch> prepared = nullptr, std::shared_ptr<const Recipe>* recipe = nullptr, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear = std::nullopt, const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews = nullptr);
|
||||
struct IndirectOutcome {
|
||||
int cpuReason;
|
||||
double argumentReadMs;
|
||||
};
|
||||
IndirectOutcome DispatchIndirect(const ShaderRecompiler::RecompileResult& shader, std::uint64_t arguments, std::span<const Graphics::GuestMemorySnapshot> snapshots = {}, std::uint64_t programAddress = 0, std::shared_ptr<PreparedDispatch> prepared = nullptr, std::shared_ptr<const Recipe>* recipe = nullptr, const std::array<std::uint32_t, 3>& threadGroup = {});
|
||||
IndirectOutcome DispatchIndirect(const ShaderRecompiler::RecompileResult& shader, std::uint64_t arguments, std::span<const Graphics::GuestMemorySnapshot> snapshots = {}, std::uint64_t programAddress = 0, std::shared_ptr<PreparedDispatch> prepared = nullptr, std::shared_ptr<const Recipe>* recipe = nullptr, const std::array<std::uint32_t, 3>& threadGroup = {}, const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews = nullptr);
|
||||
// A value-equal dispatch-cache hit with a recipe (design_cpu_final M4), in two steps.
|
||||
// PrepareRecipe, WITHOUT GuestMemory::GpuMutex: the pre-checks (recipes on, the recipe's
|
||||
// device is this one, its template and pipeline objects still alive), the template's
|
||||
@@ -388,11 +388,12 @@ public:
|
||||
private:
|
||||
VulkanDevice(const PresentationWindow* window, bool compileOnly);
|
||||
friend struct VulkanDeviceTestAccess;
|
||||
std::pair<VkBuffer, std::uint64_t> scratchPoolHeader(const ShaderRecompiler::RecompileResult& shader) const;
|
||||
VkPipeline splitComputePipeline(const Graphics::Context& context, const ShaderRecompiler::RecompileResult& shader, ComputePipelineObjects& objects, const std::array<std::uint32_t, 3>& base);
|
||||
ShaderRecompiler::SpirvTarget buildTarget() const;
|
||||
Graphics::Context buildContext() const;
|
||||
// Body of Dispatch and DispatchIndirect: `arguments` 0 dispatches x, y, z groups.
|
||||
IndirectOutcome dispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::uint64_t arguments, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t programAddress, std::shared_ptr<PreparedDispatch> prepared, std::shared_ptr<const Recipe>* recipe, const std::array<std::uint32_t, 3>& threadGroup = {}, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear = std::nullopt);
|
||||
IndirectOutcome dispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::uint64_t arguments, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t programAddress, std::shared_ptr<PreparedDispatch> prepared, std::shared_ptr<const Recipe>* recipe, const std::array<std::uint32_t, 3>& threadGroup = {}, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear = std::nullopt, const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews = nullptr);
|
||||
IndirectOutcome recordCompletedDispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::uint64_t arguments, std::uint64_t programAddress, std::shared_ptr<const Recipe>* recipeOut, const std::array<std::uint32_t, 3>& threadGroup, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear, DispatchCompletion& completion);
|
||||
// The stage-A pre-sync over `surfaces` (see PrepareDispatch): the serial waited for, 0 none.
|
||||
std::uint64_t presync(std::span<const Graphics::PresyncSurface> surfaces);
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace AgcDriver {
|
||||
void StartWorkerSampler(std::uint32_t queue = 0);
|
||||
void StartCommitterSampler();
|
||||
void StopWorkerSampler();
|
||||
bool ReadableStackRegion(std::uint64_t address, std::uint64_t& low, std::uint64_t& high);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -307,7 +307,8 @@ void Driver::dispatch(QueueState& queue, std::span<const std::uint32_t> packet,
|
||||
}
|
||||
if (fromAhead) {
|
||||
if (const auto hook = aheadAdoptHook.load(std::memory_order_acquire)) hook();
|
||||
if (!CapturedCurrent(ahead.captured, snapshot)) {
|
||||
const auto* aheadViews = ahead.capture != nullptr ? &ahead.capture->snapshot.registeredImages : ahead.keepVariant != nullptr && ahead.keepVariant->registeredViews != nullptr ? ahead.keepVariant->registeredViews.get() : nullptr;
|
||||
if (!CapturedCurrent(ahead.captured, snapshot) || (aheadViews != nullptr && !CaptureRegisteredViewsCurrent(*aheadViews))) {
|
||||
fromAhead = false;
|
||||
++dispatchesRejectedAhead;
|
||||
++groupStats.memoryMismatches;
|
||||
@@ -427,6 +428,7 @@ void Driver::dispatch(QueueState& queue, std::span<const std::uint32_t> packet,
|
||||
phaseTiming.Phase(PhaseRecompile);
|
||||
if (!resolving) insertDispatch(address, key, noDispatchCache || !CacheableResult(*compiledResult), profile, registeredShader, forgetAtCapture, memory, shaderMemory, captured, capture, compiledResult, missedEntry, missedDiffering, attachVariant, phaseTiming);
|
||||
}
|
||||
const auto* registeredViews = capture != nullptr ? &capture->snapshot.registeredImages : keepVariant != nullptr && keepVariant->registeredViews != nullptr ? keepVariant->registeredViews.get() : nullptr;
|
||||
if (resolving) {
|
||||
auto& parked = resolvedAhead()[currentPacketOffset()];
|
||||
parked = ResolvedDispatch{};
|
||||
@@ -515,7 +517,7 @@ void Driver::dispatch(QueueState& queue, std::span<const std::uint32_t> packet,
|
||||
const auto epoch = DrawPipeline::EpochToken().load(std::memory_order_relaxed);
|
||||
const auto queueId = submission.queue;
|
||||
itemCommits.fetch_add(1, std::memory_order_relaxed);
|
||||
DrawPipeline::Queue0().Enqueue([this, localDevice = std::move(localDevice), result = compiledResult, snapshots = std::move(snapshots), liveWords = std::move(liveWords), groups, address, queueId, recipe, keepVariant, dataHit, epoch, htileClearCompletion, htileMask] {
|
||||
DrawPipeline::Queue0().Enqueue([this, localDevice = std::move(localDevice), result = compiledResult, capture, registeredViews, snapshots = std::move(snapshots), liveWords = std::move(liveWords), groups, address, queueId, recipe, keepVariant, dataHit, epoch, htileClearCompletion, htileMask] {
|
||||
DrawPipeline::FollowEpoch(epoch);
|
||||
GuestMemory::SetCurrentPacket(0x15, queueId);
|
||||
const auto& compiledCommit = *result;
|
||||
@@ -526,7 +528,7 @@ void Driver::dispatch(QueueState& queue, std::span<const std::uint32_t> packet,
|
||||
bool writersNoted = false;
|
||||
for (;;) {
|
||||
std::shared_ptr<PreparedDispatch> prepared;
|
||||
if (recipeHit == nullptr || VulkanDevice::VerifyRecipes() || htileClearCompletion.has_value()) prepared = localDevice->PrepareDispatch(compiledCommit, snapshots, 0, address, htileClearCompletion);
|
||||
if (recipeHit == nullptr || VulkanDevice::VerifyRecipes() || htileClearCompletion.has_value()) prepared = localDevice->PrepareDispatch(compiledCommit, snapshots, 0, address, htileClearCompletion, registeredViews);
|
||||
GuestMemory::TagGpuLockSite(GuestMemory::GpuLockSite::Dispatch);
|
||||
std::lock_guard gpuLock(GuestMemory::GpuMutex());
|
||||
recordLabelsForPacket(localDevice.get(), queueId);
|
||||
@@ -544,7 +546,7 @@ void Driver::dispatch(QueueState& queue, std::span<const std::uint32_t> packet,
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
localDevice->Dispatch(compiledCommit, groups[0], groups[1], groups[2], snapshots, address, std::move(prepared), htileClearCompletion.has_value() ? nullptr : &builtRecipe, htileClearCompletion);
|
||||
localDevice->Dispatch(compiledCommit, groups[0], groups[1], groups[2], snapshots, address, std::move(prepared), htileClearCompletion.has_value() ? nullptr : &builtRecipe, htileClearCompletion, registeredViews);
|
||||
}
|
||||
if (htileMask.bytes != 0u) localDevice->NoteHtileMask(htileMask);
|
||||
break;
|
||||
@@ -601,7 +603,7 @@ void Driver::dispatch(QueueState& queue, std::span<const std::uint32_t> packet,
|
||||
std::shared_ptr<PreparedDispatch> prepared;
|
||||
if (recipeHit == nullptr || VulkanDevice::VerifyRecipes()) {
|
||||
try {
|
||||
prepared = localDevice->PrepareDispatch(compiled, snapshots, dispatchThreads, address, htileClearCompletion);
|
||||
prepared = localDevice->PrepareDispatch(compiled, snapshots, dispatchThreads, address, htileClearCompletion, registeredViews);
|
||||
} catch (const std::exception& error) {
|
||||
if (rethrow(error)) return;
|
||||
}
|
||||
@@ -657,10 +659,10 @@ void Driver::dispatch(QueueState& queue, std::span<const std::uint32_t> packet,
|
||||
}
|
||||
if (indirectArguments != 0) countIndirect(outcome.cpuReason, outcome.argumentReadMs);
|
||||
} else if (indirectArguments != 0) {
|
||||
const auto outcome = localDevice->DispatchIndirect(compiled, indirectArguments, snapshots, address, std::move(prepared), attachTo != nullptr ? &builtRecipe : nullptr, threadGroup);
|
||||
const auto outcome = localDevice->DispatchIndirect(compiled, indirectArguments, snapshots, address, std::move(prepared), attachTo != nullptr ? &builtRecipe : nullptr, threadGroup, registeredViews);
|
||||
countIndirect(outcome.cpuReason, outcome.argumentReadMs);
|
||||
} else {
|
||||
localDevice->Dispatch(compiled, groups[0], groups[1], groups[2], snapshots, address, std::move(prepared), htileClearCompletion.has_value() ? nullptr : (attachTo != nullptr ? &builtRecipe : nullptr), htileClearCompletion);
|
||||
localDevice->Dispatch(compiled, groups[0], groups[1], groups[2], snapshots, address, std::move(prepared), htileClearCompletion.has_value() ? nullptr : (attachTo != nullptr ? &builtRecipe : nullptr), htileClearCompletion, registeredViews);
|
||||
}
|
||||
} catch (const std::exception& error) {
|
||||
if (rethrow(error)) return;
|
||||
|
||||
@@ -66,7 +66,7 @@ Driver::DispatchCacheFootprint Driver::DispatchCacheSize() {
|
||||
|
||||
std::uint64_t Driver::variantBytes(const DispatchVariant& variant) {
|
||||
const auto held = [](const auto& values) { return static_cast<std::uint64_t>(values.capacity() * sizeof(values[0])); };
|
||||
return sizeof(DispatchVariant) + held(variant.runs) + held(variant.words) + held(variant.shared) + held(variant.dataPositions) + held(variant.dataSlots) + held(variant.runBases) + held(variant.shaderDataPatches) + held(variant.captured) + held(variant.spans) + (variant.vertexInfo != nullptr ? sizeof(ShaderRecompiler::ShaderVertexStageInfo) : 0) + (variant.memory != nullptr ? variant.memory->Bytes() : 0);
|
||||
return sizeof(DispatchVariant) + held(variant.runs) + held(variant.words) + held(variant.shared) + held(variant.dataPositions) + held(variant.dataSlots) + held(variant.runBases) + held(variant.shaderDataPatches) + held(variant.captured) + held(variant.spans) + (variant.registeredViews != nullptr ? held(*variant.registeredViews) : 0u) + (variant.vertexInfo != nullptr ? sizeof(ShaderRecompiler::ShaderVertexStageInfo) : 0) + (variant.memory != nullptr ? variant.memory->Bytes() : 0);
|
||||
}
|
||||
|
||||
void Driver::accountVariant(const DispatchVariant& variant, bool added) {
|
||||
|
||||
@@ -18,6 +18,7 @@ void Driver::insertDispatch(std::uint64_t address, std::uint64_t key, bool noDis
|
||||
if (!noDispatchCache) {
|
||||
auto fresh = std::make_shared<DispatchVariant>();
|
||||
fresh->compiled = compiledResult;
|
||||
if (capture != nullptr && !capture->snapshot.registeredImages.empty()) fresh->registeredViews = std::make_shared<const std::vector<ShaderRecompiler::RegisteredImageView>>(capture->snapshot.registeredImages);
|
||||
fresh->shader = registeredShader;
|
||||
fresh->forgetSerial = forgetAtCapture;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
|
||||
#include "Optimization/ResourceProgram.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace AgcDriver::DriverDetail {
|
||||
@@ -37,6 +38,7 @@ void Driver::lookupDispatch(std::uint64_t address, const Submission& submission,
|
||||
std::optional<SampledReadScope> sampling;
|
||||
|
||||
for (std::size_t i = 0; i < variants.size(); ++i) {
|
||||
if (variants[i]->registeredViews != nullptr && !CaptureRegisteredViewsCurrent(*variants[i]->registeredViews)) continue;
|
||||
regions.clear();
|
||||
appendEntryRegions(*variants[i], regions);
|
||||
++compared;
|
||||
@@ -58,16 +60,20 @@ void Driver::lookupDispatch(std::uint64_t address, const Submission& submission,
|
||||
current = variant != nullptr;
|
||||
} else {
|
||||
variant = variants.front();
|
||||
compared = 1;
|
||||
current = true;
|
||||
for (const auto& [begin, bytes] : variant->spans) {
|
||||
GuestMemory::CollectWrites(begin, bytes);
|
||||
if (!GuestMemory::UnchangedSince(begin, bytes, generation)) {
|
||||
current = false;
|
||||
break;
|
||||
current = variant->registeredViews == nullptr || CaptureRegisteredViewsCurrent(*variant->registeredViews);
|
||||
if (!current) variant.reset();
|
||||
if (variant != nullptr) {
|
||||
compared = 1;
|
||||
current = true;
|
||||
for (const auto& [begin, bytes] : variant->spans) {
|
||||
GuestMemory::CollectWrites(begin, bytes);
|
||||
if (!GuestMemory::UnchangedSince(begin, bytes, generation)) {
|
||||
current = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!current) {
|
||||
if (!current && variant != nullptr) {
|
||||
|
||||
std::uint64_t collected = 0;
|
||||
for (const auto& [begin, bytes] : variant->spans) collected = std::max(collected, GuestMemory::CollectWrites(begin, bytes));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/CaptureTrace.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp"
|
||||
#include "Optimization/ResourceProgram.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/CaptureTrace.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawPipeline.hpp"
|
||||
@@ -657,6 +658,7 @@ DrawVerdict Driver::draw(QueueState& queue, std::span<const std::uint32_t> packe
|
||||
throw;
|
||||
}
|
||||
for (std::size_t i = 0; i < matched.size(); ++i) {
|
||||
if (matched[i] != nullptr) stageCaptures[i].registeredViews = matched[i]->registeredViews;
|
||||
if (matched[i] == nullptr || (matched[i]->shaderDataPatches.empty() && matched[i]->descriptorPatches.empty())) continue;
|
||||
applyShaderDataPatches(*matched[i]);
|
||||
if (stageData[i].compiled != nullptr) stageData[i].compiled = patchDataWords(*matched[i], stageData[i].words);
|
||||
@@ -923,6 +925,7 @@ DrawVerdict Driver::finishDraw(DrawTail& tail, PerformanceTimer& timing) {
|
||||
const auto candidate = std::find_if(dataCandidates[i].begin(), dataCandidates[i].end(), [&](const auto& kept) { return kept.first->pushOffset == pushCursorBytes; });
|
||||
if (candidate != dataCandidates[i].end() && !verifyDrawDataHits()) {
|
||||
matched[i] = candidate->first;
|
||||
stageCaptures[i].registeredViews = matched[i]->registeredViews;
|
||||
matchedRegions[i] = std::move(candidate->second);
|
||||
reused[i] = true;
|
||||
programResults[i] = stageData[i].compiled != nullptr ? stageData[i].compiled.get() : matched[i]->compiled.get();
|
||||
@@ -955,7 +958,7 @@ DrawVerdict Driver::finishDraw(DrawTail& tail, PerformanceTimer& timing) {
|
||||
try {
|
||||
const auto slotEnd = (pushCursorBytes / Graphics::PipelinePushSlotBytes + 1u) * Graphics::PipelinePushSlotBytes;
|
||||
require(result.pushConstants.size() <= slotEnd - pushCursorBytes, "stage push constants exceed the pipeline push constant block");
|
||||
stages.push_back({program.binary.stage, &result, result.pushConstants.empty() ? 0u : pushCursorBytes});
|
||||
stages.push_back({program.binary.stage, &result, result.pushConstants.empty() ? 0u : pushCursorBytes, stageCaptures[i].registeredViews.get()});
|
||||
pushCursorBytes += static_cast<std::uint32_t>(result.pushConstants.size());
|
||||
} catch (...) {
|
||||
TraceMaterializationFailure(trace.token, submission, packetOffset, "push-constant-validation", completedSubdraws, std::current_exception());
|
||||
@@ -1058,6 +1061,7 @@ DrawVerdict Driver::finishDraw(DrawTail& tail, PerformanceTimer& timing) {
|
||||
if (!rejected.empty()) return DrawVerdict::Rejected;
|
||||
programResults[0] = compiledStages.back().get();
|
||||
stages[0].program = programResults[0];
|
||||
stages[0].registeredImageViews = stageCaptures[0].registeredViews.get();
|
||||
require(programResults[0]->pushConstants.size() == pushBytes && programResults[0]->parameterExports == exports, "pairing the mesh program with its pixel shader changed the push constants or the parameter exports the pixel shader was built for");
|
||||
}
|
||||
require(programResults[0]->meshBarycentrics == meshBarycentrics, "the mesh program was compiled for a different barycentric layout than its pixel shader");
|
||||
@@ -1175,6 +1179,7 @@ DrawVerdict Driver::finishDraw(DrawTail& tail, PerformanceTimer& timing) {
|
||||
const auto pushBytes = result.pushConstants.size();
|
||||
decodeVertexInfo(programIndex);
|
||||
result = *materializeDrawStage(programIndex, pushOffsets[programIndex], queue, submission, packetOffset, trace.token, programs, graphics, pixel, vertexInfos, memory, linked, programs[programIndex].binary.stage == Stage::TessellationControl || programs[programIndex].binary.stage == Stage::TessellationEvaluation ? direct : drawParameters, localDevice, *shaderMemory, stageCaptures, recompiled, drawHit, matched, matchedRegions, profile, dumpTarget, dumpSlot1, captures, phaseTiming, phaseMs, rejected, meshBarycentrics);
|
||||
for (auto& stage : stages) if (stage.program == &result) stage.registeredImageViews = stageCaptures[programIndex].registeredViews.get();
|
||||
if (!rejected.empty()) return DrawVerdict::Rejected;
|
||||
require(result.pushConstants.size() == pushBytes, "patched program changed its push constant layout");
|
||||
}
|
||||
|
||||
@@ -227,8 +227,8 @@ void Driver::eraseDrawEntry(std::uint64_t key, const std::shared_ptr<DrawEntry>&
|
||||
bool DecodeProgramsCurrent(const DrawDecode& decode, const ShaderRegistry&) {
|
||||
return std::all_of(decode.programs.begin(), decode.programs.end(), [&](const DrawProgram& program) {
|
||||
if (!program.snapshot->header.empty()) return true;
|
||||
return ReadRawShader(program.snapshot->codeAddress + program.codeOffset * sizeof(std::uint32_t)) == program.snapshot &&
|
||||
(program.tailContinuation == nullptr || ReadRawShader(program.tailContinuation->codeAddress) == program.tailContinuation);
|
||||
return ReadRawShader(program.snapshot->codeAddress + program.codeOffset * sizeof(std::uint32_t), program.snapshot) == program.snapshot &&
|
||||
(program.tailContinuation == nullptr || ReadRawShader(program.tailContinuation->codeAddress, program.tailContinuation) == program.tailContinuation);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@ std::shared_ptr<const ShaderRecompiler::RecompileResult> Driver::materializeDraw
|
||||
stageCapture.regions = shaderMemory.TakeRecentRegions();
|
||||
stageCapture.supplied = shaderMemory.SuppliedBlocks();
|
||||
stageCapture.userDataUse = capture->userDataUse;
|
||||
stageCapture.registeredViews = std::make_shared<const std::vector<ShaderRecompiler::RegisteredImageView>>(capture->snapshot.registeredImages);
|
||||
recompiled[i] = true;
|
||||
memory = shaderMemory.Regions();
|
||||
|
||||
@@ -225,6 +226,7 @@ void Driver::cacheDrawStages(bool useDrawEntries, bool drawHit, const Pm4::DrawP
|
||||
if (stageCapture.compiled == nullptr || !CacheableResult(*stageCapture.compiled)) continue;
|
||||
auto variant = std::make_shared<DispatchVariant>();
|
||||
variant->compiled = stageCapture.compiled;
|
||||
variant->registeredViews = stageCapture.registeredViews;
|
||||
if (programs[i].binary.stage == ShaderRecompiler::ShaderStage::Mesh) {
|
||||
std::copy_n(programs[i].userData.begin() + ShaderRecompiler::MeshIndexBufferUserWord, variant->meshIndexDescriptor.size(), variant->meshIndexDescriptor.begin());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
|
||||
#include "Optimization/ResourceProgram.hpp"
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
|
||||
@@ -141,6 +142,7 @@ void Driver::lookupDraw(const Submission& submission, const std::shared_ptr<Vulk
|
||||
bool anyLayout = false;
|
||||
for (std::size_t rank = 0; rank < variants.size(); ++rank) {
|
||||
const auto& variant = variants[rank];
|
||||
if (variant->registeredViews != nullptr && !CaptureRegisteredViewsCurrent(*variant->registeredViews)) continue;
|
||||
if (variant->pushOffset != cursor) continue;
|
||||
if (programs[i].binary.stage == ShaderRecompiler::ShaderStage::Mesh && !std::equal(variant->meshIndexDescriptor.begin(), variant->meshIndexDescriptor.end(), programs[i].userData.begin() + ShaderRecompiler::MeshIndexBufferUserWord)) {
|
||||
if (!anyLayout) outcome = EntryOutcome::Differing;
|
||||
@@ -249,6 +251,7 @@ void Driver::lookupDraw(const Submission& submission, const std::shared_ptr<Vulk
|
||||
const auto& was = dataEntry->decode->programs[i].userData;
|
||||
auto& candidates = dataCandidates[i];
|
||||
for (const auto& variant : dataEntry->stages[i]) {
|
||||
if (variant->registeredViews != nullptr && !CaptureRegisteredViewsCurrent(*variant->registeredViews)) continue;
|
||||
bool usedEqual = true;
|
||||
for (std::size_t w = 0; w < now.size() && usedEqual; ++w) {
|
||||
if (now[w] != was[w] && (w >= 64u || ((variant->userDataMask >> w) & 1u) != 0)) usedEqual = false;
|
||||
|
||||
@@ -415,6 +415,7 @@ void Driver::execute(const Submission& submission) {
|
||||
CheckFailure();
|
||||
std::uint64_t batchesAtFlip = 0, unsignaledAtFlip = 0;
|
||||
bool flipInterruptDeferred = false;
|
||||
Graphics::StorageTexture::NoteFlip();
|
||||
if (!drains) {
|
||||
|
||||
GuestMemory::TagGpuLockSite(GuestMemory::GpuLockSite::Flush);
|
||||
|
||||
@@ -16,16 +16,40 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
|
||||
namespace AgcDriver::DriverDetail {
|
||||
|
||||
namespace {
|
||||
|
||||
bool gdsWritesPending(std::span<const std::uint32_t> packet) {
|
||||
bool gdsWritesPending(std::span<const std::uint32_t> packet, const VulkanDevice* localDevice) {
|
||||
const auto address = Pm4::GdsAddress() + packet[4];
|
||||
const auto bytes = static_cast<std::size_t>(Pm4::DmaBytes(packet));
|
||||
const std::array<std::pair<std::uint64_t, std::uint64_t>, 1> range{{{address, address + bytes}}};
|
||||
return Graphics::Recorder::SnapshotWriteOverlaps(address, bytes) || Graphics::StorageTexture::AnyPendingOverlaps(range) || Graphics::AnyShadowedOverlaps(address, bytes);
|
||||
if (Graphics::Recorder::SnapshotWriteOverlaps(address, bytes) || Graphics::StorageTexture::AnyPendingOverlaps(range) || Graphics::AnyShadowedOverlaps(address, bytes)) return true;
|
||||
if (localDevice == nullptr || !Pm4::GdsImportable()) return false;
|
||||
std::lock_guard gpuLock(GuestMemory::GpuMutex());
|
||||
return localDevice->StoresPendingOver(address, bytes);
|
||||
}
|
||||
|
||||
std::uint64_t dmaAddress(std::uint32_t low, std::uint32_t high) {
|
||||
return low | (static_cast<std::uint64_t>(high) << 32u);
|
||||
}
|
||||
|
||||
bool gdsSpan(std::uint64_t offset, std::size_t bytes) {
|
||||
return offset <= Pm4::GdsBytes && bytes <= Pm4::GdsBytes - offset;
|
||||
}
|
||||
|
||||
std::optional<Pm4::MemoryCopy> decodeCopy(std::span<const std::uint32_t> packet) {
|
||||
if (auto copy = Pm4::DecodeMemoryCopy(packet)) return copy;
|
||||
if (packet.size() != 7 || !Pm4::GdsImportable()) return std::nullopt;
|
||||
const auto source = Pm4::DmaSource(packet);
|
||||
const auto destination = Pm4::DmaDestination(packet);
|
||||
const std::size_t bytes = Pm4::DmaBytes(packet);
|
||||
if (bytes == 0) return std::nullopt;
|
||||
if (source == Pm4::DmaSelectGds && (destination == 0 || destination == 3) && gdsSpan(packet[2], bytes)) return Pm4::MemoryCopy{Pm4::GdsAddress() + packet[2], dmaAddress(packet[4], packet[5]), bytes};
|
||||
if ((source == 0 || source == 3) && destination == Pm4::DmaSelectGds && gdsSpan(packet[4], bytes)) return Pm4::MemoryCopy{dmaAddress(packet[2], packet[3]), Pm4::GdsAddress() + packet[4], bytes};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -130,7 +154,7 @@ bool Driver::preparePacketMemory(const Submission& submission, QueueState& queue
|
||||
if (!drainAll && !cpuStores && (opcode == 0x40 || opcode == 0x50 || opcode == 0x83)) {
|
||||
constexpr std::size_t gpuStoreLimit = 65536;
|
||||
bool drained = true;
|
||||
const auto copy = opcode == 0x50 ? Pm4::DecodeMemoryCopy(packet) : std::nullopt;
|
||||
const auto copy = opcode == 0x50 ? decodeCopy(packet) : std::nullopt;
|
||||
const auto copyBehindPendingSource = [&] {
|
||||
if (!copy.has_value() || copy->bytes > gpuStoreLimit || !GuestMemory::Accessible(reinterpret_cast<const void*>(copy->source), copy->bytes) || !GuestMemory::Accessible(reinterpret_cast<const void*>(copy->destination), copy->bytes, true)) return false;
|
||||
const auto end = copy->source + copy->bytes;
|
||||
@@ -148,16 +172,16 @@ bool Driver::preparePacketMemory(const Submission& submission, QueueState& queue
|
||||
if (outcome.path != 1 && outcome.path != 3) throw std::runtime_error("AGC driver: a DMA_DATA copy of up to 64 KiB that GpuCopyPossible accepted took copy path " + std::to_string(outcome.path));
|
||||
return true;
|
||||
};
|
||||
if (opcode == 0x50 && packet.size() >= 7 && Pm4::DmaDestination(packet) == Pm4::DmaSelectGds) {
|
||||
if (!gdsWritesPending(packet)) {
|
||||
orderedAlready = true;
|
||||
drained = false;
|
||||
}
|
||||
} else if (copyBehindPendingSource()) {
|
||||
const bool gdsDestination = opcode == 0x50 && packet.size() >= 7 && Pm4::DmaDestination(packet) == Pm4::DmaSelectGds;
|
||||
const bool gdsOnGpu = gdsDestination && Pm4::GdsImportable();
|
||||
if ((!gdsDestination || gdsOnGpu) && copyBehindPendingSource()) {
|
||||
++copiesBehindPendingSources;
|
||||
wroteOnGpu = true;
|
||||
drained = false;
|
||||
} else if (const auto store = Pm4::ResolveStore(packet, queue, gpuStoreLimit)) {
|
||||
} else if (gdsDestination && !gdsWritesPending(packet, device.Load().get())) {
|
||||
orderedAlready = true;
|
||||
drained = false;
|
||||
} else if (const auto store = gdsDestination && !gdsOnGpu ? std::nullopt : Pm4::ResolveStore(packet, queue, gpuStoreLimit)) {
|
||||
const auto bytes = store->Bytes();
|
||||
if (bytes.empty()) {
|
||||
|
||||
@@ -313,7 +337,7 @@ void Driver::dumpSampleCounters(std::uint64_t address) {
|
||||
bool Driver::enqueueDmaPacket(std::span<const std::uint32_t> packet, std::uint32_t opcode, std::uint32_t queue, const QueueState& state) {
|
||||
if (opcode != 0x50 || queue != 0 || packet.size() < 7 || !DrawPipeline::Active() || !deferredLabels().labels.empty()) return false;
|
||||
const auto source = ((packet[1] >> 29u) & 3u) | ((packet[6] >> 24u) & 4u) | ((packet[6] >> 25u) & 8u);
|
||||
if (Pm4::DmaDestination(packet) == Pm4::DmaSelectGds && gdsWritesPending(packet)) return false;
|
||||
if (Pm4::DmaDestination(packet) == Pm4::DmaSelectGds && gdsWritesPending(packet, device.Load().get())) return false;
|
||||
constexpr std::size_t immediateLimit = std::size_t{16} << 20u;
|
||||
constexpr std::size_t gpuStoreLimit = 65536;
|
||||
if (source == 2 && Pm4::DmaBytes(packet) > gpuStoreLimit && Pm4::DmaDestination(packet) != Pm4::DmaSelectGds) {
|
||||
|
||||
@@ -227,8 +227,7 @@ void Driver::run(std::uint32_t id) noexcept {
|
||||
const auto idleEpochAtWait = idleEpoch.load(std::memory_order_acquire);
|
||||
changed.wait(lock, [&] { return ready() || (id == 0 && (idleEpoch.load(std::memory_order_acquire) != idleEpochAtWait || completionsPending())); });
|
||||
if (id == 0) queue0Dormant.store(false, std::memory_order_relaxed);
|
||||
if (id == 0 && !ready() && (idleEpoch.load(std::memory_order_acquire) != idleEpochAtWait || completionsPending())) continue;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (poll(ready)) break;
|
||||
lock.unlock();
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Mutex.hpp"
|
||||
#include "ControlFlow/RequestSerializer.hpp"
|
||||
#include "Optimization/ResourceProgram.hpp"
|
||||
#include <charconv>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#ifdef _WIN32
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -11,6 +20,15 @@ namespace AgcDriver::DriverDetail {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string captureSession() {
|
||||
#ifdef _WIN32
|
||||
const auto process = _getpid();
|
||||
#else
|
||||
const auto process = getpid();
|
||||
#endif
|
||||
return std::to_string(process) + "-" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count());
|
||||
}
|
||||
|
||||
std::optional<std::set<std::uint64_t>> selectedPrograms() {
|
||||
const char* value = std::getenv("APS5_DUMP_SHADERS");
|
||||
if (value == nullptr || std::string_view(value) == "1") return std::nullopt;
|
||||
@@ -32,6 +50,46 @@ std::optional<std::set<std::uint64_t>> selectedPrograms() {
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<const ShaderRecompiler::SourceHandle> PrepareShaderWithDiagnostics(const ShaderRecompiler::RecompileRequest& request, ShaderRecompiler::ShaderPreparationContext* preparation) {
|
||||
std::exception_ptr failure;
|
||||
std::string dump;
|
||||
static const bool dumpInputs = std::getenv("APS5_DUMP_PREPARE_INPUTS") != nullptr;
|
||||
std::string inputDump;
|
||||
if (dumpInputs) {
|
||||
try {
|
||||
static const auto session = captureSession();
|
||||
static std::atomic<std::uint64_t> next{0};
|
||||
const auto suffix = ".input-" + session + "-" + std::to_string(next.fetch_add(1)) + ".prepare";
|
||||
inputDump = Driver::dumpRequest(request.shader.codeAddress, request, suffix);
|
||||
if (!inputDump.empty()) {
|
||||
std::fprintf(stderr, "[prepare-input] begin %s\n", inputDump.c_str());
|
||||
std::fflush(stderr);
|
||||
}
|
||||
} catch (const std::exception& error) {
|
||||
std::fprintf(stderr, "[prepare-input] capture failed: %s\n", error.what());
|
||||
}
|
||||
}
|
||||
try {
|
||||
auto handle = ShaderRecompiler::PrepareShader(request, preparation);
|
||||
if (!inputDump.empty()) std::fprintf(stderr, "[prepare-input] end %s\n", inputDump.c_str());
|
||||
return handle;
|
||||
} catch (...) {
|
||||
failure = std::current_exception();
|
||||
try {
|
||||
if (std::getenv("APS5_DUMP_SHADERS") != nullptr) dump = Driver::dumpRequest(request.shader.codeAddress, request, ".prepare");
|
||||
} catch (...) {}
|
||||
}
|
||||
try {
|
||||
std::rethrow_exception(failure);
|
||||
} catch (const std::exception& error) {
|
||||
std::ostringstream where;
|
||||
where << "shader 0x" << std::hex << request.shader.codeAddress << " stage " << static_cast<unsigned>(request.shader.stage);
|
||||
if (!dump.empty()) where << " (" << dump << ")";
|
||||
where << ": ";
|
||||
throw std::runtime_error(where.str() + error.what());
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::reportSkip(const char* kind, const std::string& what) {
|
||||
static AgcDriver::Mutex reportedMutex;
|
||||
static std::set<std::size_t> reported;
|
||||
@@ -96,14 +154,17 @@ std::string Driver::dumpRequest(std::uint64_t address, const ShaderRecompiler::R
|
||||
if (written != text.size() || closed != 0) {
|
||||
dumped.erase(name);
|
||||
std::fprintf(stderr, "[gpu] incomplete write to dump file %s (%zu of %zu bytes, close status %d)\n", name.c_str(), written, text.size(), closed);
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
dumped.erase(name);
|
||||
std::fprintf(stderr, "[gpu] could not open dump file %s for writing\n", name.c_str());
|
||||
return {};
|
||||
}
|
||||
} catch (const std::exception& error) {
|
||||
dumped.erase(name);
|
||||
std::fprintf(stderr, "[gpu] could not serialize request for 0x%llx: %s\n", static_cast<unsigned long long>(address), error.what());
|
||||
return {};
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -60,30 +60,8 @@
|
||||
|
||||
namespace AgcDriver::DriverDetail {
|
||||
|
||||
std::shared_ptr<const ShaderRecompiler::SourceHandle> PrepareShaderWithDiagnostics(const ShaderRecompiler::RecompileRequest& request, ShaderRecompiler::ShaderPreparationContext* preparation) {
|
||||
std::exception_ptr failure;
|
||||
std::string dump;
|
||||
try {
|
||||
auto handle = ShaderRecompiler::PrepareShader(request, preparation);
|
||||
return handle;
|
||||
} catch (...) {
|
||||
failure = std::current_exception();
|
||||
try {
|
||||
if (std::getenv("APS5_DUMP_SHADERS") != nullptr) dump = Driver::dumpRequest(request.shader.codeAddress, request, ".prepare");
|
||||
} catch (...) {}
|
||||
}
|
||||
try {
|
||||
std::rethrow_exception(failure);
|
||||
} catch (const std::exception& error) {
|
||||
std::ostringstream where;
|
||||
where << "shader 0x" << std::hex << request.shader.codeAddress << " stage " << static_cast<unsigned>(request.shader.stage);
|
||||
if (!dump.empty()) where << " (" << dump << ")";
|
||||
where << ": ";
|
||||
throw std::runtime_error(where.str() + error.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<const ShaderSnapshot> ReadRawShader(std::uint64_t address) {
|
||||
std::shared_ptr<const ShaderSnapshot> ReadRawShader(std::uint64_t address, const std::shared_ptr<const ShaderSnapshot>& retained) {
|
||||
const auto drain = [](std::uint64_t first, std::size_t bytes) {
|
||||
if (!DrawPipeline::Active()) return;
|
||||
auto& pipeline = DrawPipeline::Queue0();
|
||||
@@ -92,8 +70,8 @@ std::shared_ptr<const ShaderSnapshot> ReadRawShader(std::uint64_t address) {
|
||||
static std::mutex cacheMutex;
|
||||
static std::list<std::shared_ptr<const ShaderSnapshot>> cache;
|
||||
static std::size_t cacheBytes = 0;
|
||||
std::shared_ptr<const ShaderSnapshot> cached;
|
||||
{
|
||||
std::shared_ptr<const ShaderSnapshot> cached = retained != nullptr && retained->codeAddress == address && retained->header.empty() && !retained->code.empty() ? retained : nullptr;
|
||||
if (cached == nullptr) {
|
||||
std::lock_guard lock(cacheMutex);
|
||||
const auto found = std::find_if(cache.begin(), cache.end(), [address](const auto& entry) { return entry->codeAddress == address; });
|
||||
if (found != cache.end()) cached = *found;
|
||||
@@ -902,6 +880,10 @@ void ReportPreparedAtUse(const ShaderSnapshot& snapshot, const ShaderRecompiler:
|
||||
APS5_LOG_OUT_DEBUG("Shader 0x%llx samples a converted image; preparing its converted-sample variant at use", static_cast<unsigned long long>(request.shader.codeAddress));
|
||||
return;
|
||||
}
|
||||
if (request.context.layerRowSamples) {
|
||||
APS5_LOG_OUT_DEBUG("Shader 0x%llx samples a 1D array past maxImageArrayLayers; preparing its layer-row variant at use", static_cast<unsigned long long>(request.shader.codeAddress));
|
||||
return;
|
||||
}
|
||||
if (snapshot.codeAddress == NullPixelProgramAddress() && request.shader.stage == ShaderRecompiler::ShaderStage::Fragment && request.context.waveSize == 32u) {
|
||||
APS5_LOG_ERR("The null pixel program has no wave%u artifact for this draw; preparing it at draw", request.context.waveSize);
|
||||
return;
|
||||
@@ -1163,6 +1145,7 @@ ShaderRecompiler::PreparedShaderInvocation InvocationFor(const ShaderSnapshot& s
|
||||
std::unique_lock lock(snapshot.prepared->mutex);
|
||||
AwaitRegisteredPreparation(*snapshot.prepared, lock);
|
||||
if (std::ranges::find(snapshot.prepared->convertedSamples, codeOffset) != snapshot.prepared->convertedSamples.end()) source.context.convertedSamples = true;
|
||||
if (std::ranges::find(snapshot.prepared->layerRowSamples, codeOffset) != snapshot.prepared->layerRowSamples.end()) source.context.layerRowSamples = true;
|
||||
auto invocationRequest = source;
|
||||
struct PreparedKeyStorage {};
|
||||
auto& key = HostThreadLocal<std::vector<std::uint64_t>, PreparedKeyStorage>();
|
||||
@@ -1190,18 +1173,22 @@ ShaderRecompiler::PreparedShaderInvocation InvocationFor(const ShaderSnapshot& s
|
||||
}
|
||||
|
||||
std::shared_ptr<const ShaderRecompiler::ResourceCapture> CaptureInvocation(ShaderMemory& memory, const ShaderSnapshot& snapshot, std::size_t codeOffset, const ShaderRecompiler::RecompileRequest& request, ShaderRecompiler::PreparedShaderInvocation& invocation) {
|
||||
try {
|
||||
return memory.Capture(invocation);
|
||||
} catch (const ShaderRecompiler::ConvertedSampleRequired&) {
|
||||
if (invocation.Request().context.convertedSamples) throw;
|
||||
}
|
||||
{
|
||||
const auto record = [&](std::vector<std::size_t>& offsets) {
|
||||
std::lock_guard lock(snapshot.prepared->mutex);
|
||||
auto& offsets = snapshot.prepared->convertedSamples;
|
||||
if (std::ranges::find(offsets, codeOffset) == offsets.end()) offsets.push_back(codeOffset);
|
||||
};
|
||||
while (true) {
|
||||
try {
|
||||
return memory.Capture(invocation);
|
||||
} catch (const ShaderRecompiler::ConvertedSampleRequired&) {
|
||||
if (invocation.Request().context.convertedSamples) throw;
|
||||
record(snapshot.prepared->convertedSamples);
|
||||
} catch (const ShaderRecompiler::LayerRowSamplesRequired&) {
|
||||
if (invocation.Request().context.layerRowSamples) throw;
|
||||
record(snapshot.prepared->layerRowSamples);
|
||||
}
|
||||
invocation = InvocationFor(snapshot, codeOffset, request);
|
||||
}
|
||||
invocation = InvocationFor(snapshot, codeOffset, request);
|
||||
return memory.Capture(invocation);
|
||||
}
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -1057,11 +1057,11 @@ struct WriteTracker {
|
||||
static constexpr std::size_t CoarseBlocks = 64;
|
||||
static constexpr std::size_t LeafBlocks = std::size_t{1} << 16;
|
||||
struct Leaf {
|
||||
std::array<std::uint32_t, LeafBlocks> blocks{};
|
||||
std::array<std::uint32_t, LeafBlocks> cpuBlocks{};
|
||||
std::array<std::uint32_t, LeafBlocks / CoarseBlocks> coarseBlocks{};
|
||||
std::array<std::uint64_t, LeafBlocks> blocks{};
|
||||
std::array<std::uint64_t, LeafBlocks> cpuBlocks{};
|
||||
std::array<std::uint64_t, LeafBlocks / CoarseBlocks> coarseBlocks{};
|
||||
#ifdef _WIN32
|
||||
std::array<std::uint32_t, LeafBlocks> hintBlocks{};
|
||||
std::array<std::uint64_t, LeafBlocks> hintBlocks{};
|
||||
#endif
|
||||
};
|
||||
std::vector<std::unique_ptr<Leaf>> leaves;
|
||||
@@ -1076,8 +1076,8 @@ struct WriteTracker {
|
||||
// stamp still happen under it): a hit must return the current value, including MarkWritten
|
||||
// bumps, or an image refreshed after a stamp would keep failing UnchangedSince until the next
|
||||
// walk of its range and re-upload at every use of the epoch.
|
||||
std::atomic<std::uint32_t> generation{1};
|
||||
std::atomic<std::uint32_t> stable{1};
|
||||
std::atomic<std::uint64_t> generation{1};
|
||||
std::atomic<std::uint64_t> stable{1};
|
||||
std::vector<void*> pages;
|
||||
// Collect memo: page-rounded ranges walked during the current epoch (see BumpCollectEpoch). A
|
||||
// collect fully inside one skips GetWriteWatch, whose cost is proportional to the range's pages,
|
||||
@@ -1160,24 +1160,24 @@ struct WriteTracker {
|
||||
return !GuestArena::GuestArenaHostRegionOverlaps_nid_postfix(static_cast<std::uintptr_t>(first), static_cast<std::size_t>(stop - first));
|
||||
}
|
||||
|
||||
std::uint32_t newestHint(std::uint64_t first, std::uint64_t stop) const {
|
||||
std::uint32_t newest = 0;
|
||||
std::uint64_t newestHint(std::uint64_t first, std::uint64_t stop) const {
|
||||
std::uint64_t newest = 0;
|
||||
for (auto block = blockOf(first); block <= blockOf(stop - 1); ++block) newest = std::max(newest, hintOf(block));
|
||||
return newest;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct DriverPiece {
|
||||
std::uint32_t generation = 0;
|
||||
std::uint64_t generation = 0;
|
||||
std::uint32_t begin = 0;
|
||||
std::uint32_t end = 0;
|
||||
};
|
||||
struct DriverPieces {
|
||||
std::uint32_t whole = 0;
|
||||
std::uint32_t dropped = 0;
|
||||
std::uint64_t whole = 0;
|
||||
std::uint64_t dropped = 0;
|
||||
std::array<DriverPiece, 4> pieces{};
|
||||
std::uint32_t possibleWhole = 0;
|
||||
std::uint32_t possibleDropped = 0;
|
||||
std::uint64_t possibleWhole = 0;
|
||||
std::uint64_t possibleDropped = 0;
|
||||
std::array<DriverPiece, 4> possiblePieces{};
|
||||
|
||||
bool covers(std::uint32_t begin, std::uint32_t end, std::uint64_t generation) const {
|
||||
@@ -1197,21 +1197,21 @@ struct WriteTracker {
|
||||
std::unordered_map<std::uint64_t, DriverPieces> driverPieces;
|
||||
|
||||
struct CpuPages {
|
||||
std::array<std::uint32_t, WritePagesPerBlock> pages{};
|
||||
std::array<std::uint64_t, WritePagesPerBlock> pages{};
|
||||
};
|
||||
std::unordered_map<std::uint64_t, CpuPages> cpuPages;
|
||||
std::unordered_map<std::uint64_t, CpuPages> walkPages;
|
||||
std::map<std::uint64_t, std::uint32_t> refused;
|
||||
std::map<std::uint64_t, std::uint64_t> refused;
|
||||
|
||||
void noteCpuStore(std::uint64_t begin, std::uint64_t end, std::uint32_t stampGeneration) {
|
||||
void noteCpuStore(std::uint64_t begin, std::uint64_t end, std::uint64_t stampGeneration) {
|
||||
notePages(cpuPages, begin, end, stampGeneration);
|
||||
}
|
||||
|
||||
void noteWalkStore(std::uint64_t begin, std::uint64_t end, std::uint32_t stampGeneration) {
|
||||
void noteWalkStore(std::uint64_t begin, std::uint64_t end, std::uint64_t stampGeneration) {
|
||||
notePages(walkPages, begin, end, stampGeneration);
|
||||
}
|
||||
|
||||
void notePages(std::unordered_map<std::uint64_t, CpuPages>& pages, std::uint64_t begin, std::uint64_t end, std::uint32_t stampGeneration) {
|
||||
void notePages(std::unordered_map<std::uint64_t, CpuPages>& pages, std::uint64_t begin, std::uint64_t end, std::uint64_t stampGeneration) {
|
||||
for (auto block = blockOf(begin); block <= blockOf(end - 1); ++block) {
|
||||
const auto blockStart = blockBegin(block);
|
||||
const auto from = std::max(begin, blockStart) - blockStart;
|
||||
@@ -1235,7 +1235,7 @@ struct WriteTracker {
|
||||
#endif
|
||||
}
|
||||
|
||||
void stampWatchedPart(std::uint64_t address, std::uint64_t end, std::uint32_t stampGeneration, bool complete) {
|
||||
void stampWatchedPart(std::uint64_t address, std::uint64_t end, std::uint64_t stampGeneration, bool complete) {
|
||||
#ifdef _WIN32
|
||||
address = std::max<std::uint64_t>(address, base);
|
||||
end = std::min<std::uint64_t>(end, base + size);
|
||||
@@ -1253,7 +1253,7 @@ struct WriteTracker {
|
||||
}
|
||||
}
|
||||
|
||||
void noteDriverStore(std::uint64_t block, std::uint64_t address, std::uint64_t end, std::uint32_t stampGeneration, bool complete) {
|
||||
void noteDriverStore(std::uint64_t block, std::uint64_t address, std::uint64_t end, std::uint64_t stampGeneration, bool complete) {
|
||||
const auto begin = blockBegin(block);
|
||||
const auto from = static_cast<std::uint32_t>(std::max(address, begin) - begin);
|
||||
const auto to = static_cast<std::uint32_t>(std::min<std::uint64_t>(end, begin + WriteBlockBytes) - begin);
|
||||
@@ -1301,19 +1301,19 @@ struct WriteTracker {
|
||||
leafFor(block).hintBlocks[block % LeafBlocks] = generation;
|
||||
}
|
||||
|
||||
std::uint32_t hintOf(std::uint64_t block) const {
|
||||
std::uint64_t hintOf(std::uint64_t block) const {
|
||||
const auto& leaf = leaves[block / LeafBlocks];
|
||||
return leaf != nullptr ? leaf->hintBlocks[block % LeafBlocks] : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::uint32_t stampOf(std::uint64_t block) const {
|
||||
std::uint64_t stampOf(std::uint64_t block) const {
|
||||
const auto& leaf = leaves[block / LeafBlocks];
|
||||
return leaf != nullptr ? leaf->blocks[block % LeafBlocks] : 0;
|
||||
}
|
||||
|
||||
static constexpr std::size_t UnstampedSlots = 1u << 16;
|
||||
std::vector<std::uint32_t> unstampedStores;
|
||||
std::vector<std::uint64_t> unstampedStores;
|
||||
|
||||
void noteUnstampedStore(std::uint64_t address, std::uint64_t end) {
|
||||
if (unstampedStores.empty()) unstampedStores.assign(UnstampedSlots, 0);
|
||||
@@ -1326,8 +1326,8 @@ struct WriteTracker {
|
||||
for (auto block = first; block <= last; ++block) unstampedStores[block % UnstampedSlots] = generation;
|
||||
}
|
||||
|
||||
std::uint32_t newestStamp(std::uint64_t address, std::uint64_t end) const {
|
||||
std::uint32_t newest = 0;
|
||||
std::uint64_t newestStamp(std::uint64_t address, std::uint64_t end) const {
|
||||
std::uint64_t newest = 0;
|
||||
if (!unstampedStores.empty()) {
|
||||
const auto first = address / WriteBlockBytes;
|
||||
const auto last = (end - 1) / WriteBlockBytes;
|
||||
@@ -1346,14 +1346,14 @@ struct WriteTracker {
|
||||
return newest;
|
||||
}
|
||||
|
||||
std::uint32_t coarseStampOf(std::uint64_t block) const {
|
||||
std::uint64_t coarseStampOf(std::uint64_t block) const {
|
||||
const auto& leaf = leaves[block / LeafBlocks];
|
||||
return leaf != nullptr ? leaf->coarseBlocks[(block % LeafBlocks) / CoarseBlocks] : 0;
|
||||
}
|
||||
|
||||
bool unchanged(std::uint64_t first, std::uint64_t last, std::uint64_t since) const {
|
||||
if (first == last) return stampOf(first) <= since;
|
||||
const auto newer = [since](std::uint32_t stamp) { return stamp > since; };
|
||||
const auto newer = [since](std::uint64_t stamp) { return stamp > since; };
|
||||
while (first <= last) {
|
||||
const auto& leaf = leaves[first / LeafBlocks];
|
||||
if (leaf == nullptr) {
|
||||
@@ -1370,7 +1370,7 @@ struct WriteTracker {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::uint32_t cpuStampOf(std::uint64_t block) const {
|
||||
std::uint64_t cpuStampOf(std::uint64_t block) const {
|
||||
const auto& leaf = leaves[block / LeafBlocks];
|
||||
return leaf != nullptr ? leaf->cpuBlocks[block % LeafBlocks] : 0;
|
||||
}
|
||||
@@ -1422,7 +1422,7 @@ struct WriteTracker {
|
||||
return unchanged(blockOf(address), blockOf(address + bytes - 1), since) || !storedOver(address, address + bytes, since, true);
|
||||
}
|
||||
|
||||
void stamp(std::uint64_t block, std::uint32_t stampGeneration, StampKind kind) {
|
||||
void stamp(std::uint64_t block, std::uint64_t stampGeneration, StampKind kind) {
|
||||
const bool cpu = kind == StampKind::Cpu || kind == StampKind::ImportWindow;
|
||||
const bool stored = kind != StampKind::ImportWindow;
|
||||
auto& leaf = leafFor(block);
|
||||
@@ -1516,7 +1516,7 @@ void watchPrivateMapping(std::uintptr_t address, std::size_t bytes, std::uint64_
|
||||
tracker.noteCpuStore(address, address + bytes, tracker.generation);
|
||||
for (auto block = tracker.blockOf(address); block <= tracker.blockOf(address + bytes - 1); ++block) {
|
||||
if (const auto& leaf = tracker.leaves[block / WriteTracker::LeafBlocks]; leaf != nullptr) leaf->hintBlocks[block % WriteTracker::LeafBlocks] = 0;
|
||||
if (const auto found = tracker.driverPieces.find(block); found != tracker.driverPieces.end()) found->second.dropped = std::max<std::uint32_t>(found->second.dropped, tracker.generation);
|
||||
if (const auto found = tracker.driverPieces.find(block); found != tracker.driverPieces.end()) found->second.dropped = std::max<std::uint64_t>(found->second.dropped, tracker.generation);
|
||||
tracker.stamp(block, tracker.generation, StampKind::Cpu);
|
||||
}
|
||||
unwatchSerial.fetch_add(1, std::memory_order_release);
|
||||
@@ -1593,7 +1593,7 @@ struct StampRuns {
|
||||
std::vector<std::pair<std::uint64_t, std::uint64_t>> windowRuns;
|
||||
};
|
||||
|
||||
void noteWrittenRun(StampRuns& runs, std::uintptr_t begin, std::uintptr_t end, std::uint32_t generation) {
|
||||
void noteWrittenRun(StampRuns& runs, std::uintptr_t begin, std::uintptr_t end, std::uint64_t generation) {
|
||||
if (runs.kind != StampKind::Driver) runs.tracker.noteCpuStore(begin, end, generation);
|
||||
else runs.tracker.noteWalkStore(begin, end, generation);
|
||||
}
|
||||
@@ -1741,7 +1741,8 @@ std::uint64_t collectWrites(std::uint64_t address, std::size_t bytes, bool memoi
|
||||
}
|
||||
}
|
||||
const TimedAccess timed(CounterCollect, bytes);
|
||||
#ifndef _WIN32
|
||||
const auto requestedFirst = first;
|
||||
const auto requestedStop = stop;
|
||||
if (useMemo && HostThreadSlot<std::uint64_t, CollectEpochSlot>::Get() != 0 && bytes <= WriteBlockBytes) {
|
||||
const auto begin = first & ~(WriteBlockBytes - 1);
|
||||
const auto end = (stop + WriteBlockBytes - 1) & ~(WriteBlockBytes - 1);
|
||||
@@ -1750,8 +1751,16 @@ std::uint64_t collectWrites(std::uint64_t address, std::size_t bytes, bool memoi
|
||||
stop = end;
|
||||
}
|
||||
}
|
||||
if (!walkWrites(tracker, first, stop, StampKind::Cpu)) {
|
||||
#ifdef _WIN32
|
||||
if (first == requestedFirst && stop == requestedStop) return 0;
|
||||
first = requestedFirst;
|
||||
stop = requestedStop;
|
||||
if (!walkWrites(tracker, first, stop, StampKind::Cpu)) return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
if (!walkWrites(tracker, first, stop, StampKind::Cpu)) return 0;
|
||||
}
|
||||
// Only a completed walk is remembered; a failed one (uncommitted pages) returned 0 above.
|
||||
if (collectMemoEnabled()) {
|
||||
const auto serial = unwatchSerial.load(std::memory_order_relaxed);
|
||||
@@ -2299,6 +2308,12 @@ std::uint64_t TrackerGeneration() {
|
||||
return tracker.generation;
|
||||
}
|
||||
|
||||
void AdvanceTrackerGenerationForTest(std::uint64_t generation) {
|
||||
auto& tracker = Tracker();
|
||||
const auto lock = lockTracker(tracker);
|
||||
if (generation > tracker.generation.load(std::memory_order_relaxed)) tracker.generation.store(generation, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::uint64_t NewestStamp(std::uint64_t address, std::size_t bytes) {
|
||||
auto& tracker = Tracker();
|
||||
const auto lock = lockTracker(tracker);
|
||||
@@ -3024,7 +3039,7 @@ void WriteChanged(std::uint64_t address, std::span<const std::byte> current, std
|
||||
WriteChanged(address, current, original, ChangedByteStoreLimit());
|
||||
}
|
||||
|
||||
void WriteChanged(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original, std::uint32_t byteStoreLimit) {
|
||||
static void writeChanged(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original, std::uint32_t byteStoreLimit, bool keepGuest) {
|
||||
require(current.size() == original.size(), "write-back snapshot sizes differ");
|
||||
BreakProofs();
|
||||
if (current.empty()) return;
|
||||
@@ -3044,7 +3059,9 @@ void WriteChanged(std::uint64_t address, std::span<const std::byte> current, std
|
||||
std::size_t at = 0;
|
||||
for (; at + 16 <= size; at += 16) {
|
||||
const auto bytes = _mm_loadu_si128(reinterpret_cast<const __m128i*>(current.data() + at));
|
||||
const auto same = _mm_cmpeq_epi8(bytes, _mm_loadu_si128(reinterpret_cast<const __m128i*>(original.data() + at)));
|
||||
const auto uploaded = _mm_loadu_si128(reinterpret_cast<const __m128i*>(original.data() + at));
|
||||
auto same = _mm_cmpeq_epi8(bytes, uploaded);
|
||||
if (keepGuest) same = _mm_or_si128(same, _mm_xor_si128(_mm_cmpeq_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(destination + at)), uploaded), _mm_set1_epi8(-1)));
|
||||
const auto equal = static_cast<std::uint32_t>(_mm_movemask_epi8(same));
|
||||
if (equal == 0xffffu) continue;
|
||||
const auto changed = ~equal & 0xffffu;
|
||||
@@ -3063,7 +3080,7 @@ void WriteChanged(std::uint64_t address, std::span<const std::byte> current, std
|
||||
}
|
||||
if (masked) _mm_sfence();
|
||||
for (; at < size; ++at) {
|
||||
if (current[at] == original[at]) continue;
|
||||
if (current[at] == original[at] || (keepGuest && destination[at] != original[at])) continue;
|
||||
destination[at] = current[at];
|
||||
firstChanged = std::min(firstChanged, at);
|
||||
lastChanged = std::max(lastChanged, at + 1);
|
||||
@@ -3072,6 +3089,14 @@ void WriteChanged(std::uint64_t address, std::span<const std::byte> current, std
|
||||
});
|
||||
}
|
||||
|
||||
void WriteChanged(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original, std::uint32_t byteStoreLimit) {
|
||||
writeChanged(address, current, original, byteStoreLimit, false);
|
||||
}
|
||||
|
||||
void WriteChangedKeepingGuest(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original) {
|
||||
writeChanged(address, current, original, ChangedByteStoreLimit(), true);
|
||||
}
|
||||
|
||||
void Write(std::uint64_t address, std::span<const std::byte> source, std::size_t alignment) {
|
||||
if (source.empty()) return;
|
||||
// A store, as in WriteChanged.
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <cerrno>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
extern char** environ;
|
||||
#endif
|
||||
|
||||
namespace AgcDriver {
|
||||
|
||||
@@ -372,7 +372,20 @@ OverlayLayout LayOutKeyboard(const ImeKeyboardView& view, VkExtent2D extent) {
|
||||
const auto inner = gridWidth(view);
|
||||
rect(KeyboardMetrics::Padding, KeyboardMetrics::Padding, inner, KeyboardMetrics::FieldHeight, OverlayColor::Field);
|
||||
std::size_t caret = 0;
|
||||
const auto characters = decode(view.text, view.caret, &caret);
|
||||
auto characters = decode(view.text, view.caret, &caret);
|
||||
std::vector<std::uint8_t> marks(characters.size(), 0);
|
||||
if (!view.preedit.empty()) {
|
||||
Graphics::Require(view.preeditCursor <= view.preedit.size() && view.preeditSelection <= view.preedit.size() - view.preeditCursor, "the system keyboard composition cursor is past its text");
|
||||
std::size_t cursor = 0;
|
||||
std::size_t selectionEnd = 0;
|
||||
const auto composed = decode(view.preedit, view.preeditCursor, &cursor);
|
||||
decode(view.preedit, view.preeditCursor + view.preeditSelection, &selectionEnd);
|
||||
std::vector<std::uint8_t> composedMarks(composed.size(), KeyboardCompositionMark);
|
||||
std::fill(composedMarks.begin() + static_cast<std::ptrdiff_t>(cursor), composedMarks.begin() + static_cast<std::ptrdiff_t>(selectionEnd), KeyboardSelectionMark);
|
||||
characters.insert(characters.begin() + static_cast<std::ptrdiff_t>(caret), composed.begin(), composed.end());
|
||||
marks.insert(marks.begin() + static_cast<std::ptrdiff_t>(caret), composedMarks.begin(), composedMarks.end());
|
||||
caret += cursor;
|
||||
}
|
||||
const auto textLeft = KeyboardMetrics::Padding + KeyboardMetrics::FieldInset;
|
||||
const auto textTop = KeyboardMetrics::Padding + KeyboardMetrics::FieldInset;
|
||||
const auto visible = static_cast<std::size_t>((inner - 2 * KeyboardMetrics::FieldInset + 1) / KeyboardMetrics::Advance);
|
||||
@@ -381,6 +394,8 @@ OverlayLayout LayOutKeyboard(const ImeKeyboardView& view, VkExtent2D extent) {
|
||||
for (auto index = first; index < last; ++index) {
|
||||
const auto column = static_cast<std::int32_t>(index - first);
|
||||
glyph(layout, KeyboardGlyph(characters[index]), left + (textLeft + column * KeyboardMetrics::Advance) * scale, top + textTop * scale, scale, OverlayColor::Text);
|
||||
if (marks[index] == KeyboardCompositionMark) rect(textLeft + column * KeyboardMetrics::Advance, textTop + KeyboardMetrics::GlyphHeight, KeyboardMetrics::Advance, 1, OverlayColor::Accent);
|
||||
else if (marks[index] == KeyboardSelectionMark) rect(textLeft + column * KeyboardMetrics::Advance, textTop + KeyboardMetrics::GlyphHeight, KeyboardMetrics::Advance, 2, OverlayColor::Text);
|
||||
}
|
||||
rect(textLeft + static_cast<std::int32_t>(caret - first) * KeyboardMetrics::Advance - 1, KeyboardMetrics::Padding + 1, 1, KeyboardMetrics::FieldHeight - 2, OverlayColor::Accent);
|
||||
for (const auto& key : view.keys) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
@@ -16,10 +17,55 @@
|
||||
|
||||
namespace AgcDriver::Pm4 {
|
||||
|
||||
namespace {
|
||||
|
||||
std::atomic<bool> importableGdsRequested{false};
|
||||
std::atomic<bool> gdsShared{false};
|
||||
std::atomic<bool> gdsImportable{false};
|
||||
|
||||
}
|
||||
|
||||
void RequestImportableGds(bool requested) {
|
||||
importableGdsRequested.store(requested, std::memory_order_release);
|
||||
}
|
||||
|
||||
bool ImportableGdsRequested() {
|
||||
return importableGdsRequested.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
bool GdsShared() {
|
||||
static_cast<void>(GdsAddress());
|
||||
return gdsShared.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
bool GdsImportable() {
|
||||
static_cast<void>(GdsAddress());
|
||||
return gdsImportable.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void RejectGdsImport() {
|
||||
gdsImportable.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
std::uint64_t GdsAddress() {
|
||||
static const std::uint64_t address = [] {
|
||||
constexpr int ReadWrite = 0x3;
|
||||
constexpr int PrivateAnonymous = 0x1002;
|
||||
constexpr int Shared = 0x1;
|
||||
constexpr int OpenReadWrite = 0x2;
|
||||
const char* const anonymousSharedMemory = reinterpret_cast<const char*>(1);
|
||||
if (ImportableGdsRequested() && std::getenv("APS5_NO_SHARED_GDS") == nullptr) {
|
||||
if (const int descriptor = shm_open_nid_postfix(anonymousSharedMemory, OpenReadWrite, 0600); descriptor >= 0) {
|
||||
void* shared = ftruncate_nid_postfix(descriptor, GdsBytes) == 0 ? mmap_nid_postfix(nullptr, GdsBytes, ReadWrite, Shared, descriptor, 0) : nullptr;
|
||||
close_nid_postfix(descriptor);
|
||||
if (shared != nullptr && shared != reinterpret_cast<void*>(static_cast<std::uintptr_t>(-1))) {
|
||||
std::memset(shared, 0, GdsBytes);
|
||||
gdsShared.store(true, std::memory_order_release);
|
||||
gdsImportable.store(true, std::memory_order_release);
|
||||
return reinterpret_cast<std::uint64_t>(shared);
|
||||
}
|
||||
}
|
||||
}
|
||||
void* mapped = mmap_nid_postfix(nullptr, GdsBytes, ReadWrite, PrivateAnonymous, -1, 0);
|
||||
if (mapped == nullptr || mapped == reinterpret_cast<void*>(static_cast<std::uintptr_t>(-1))) throw std::runtime_error("cannot allocate the global data share");
|
||||
return reinterpret_cast<std::uint64_t>(mapped);
|
||||
@@ -289,7 +335,7 @@ void Validate(std::span<const std::uint32_t> packet, std::uint32_t queue) {
|
||||
// Header bit 1 selects the compute shader type and bit 2 (register writes) resets the filter CAM;
|
||||
// neither changes what the packet writes.
|
||||
const auto flags = header & 0xffu;
|
||||
const bool registerWrite = opcode == 0x69 || opcode == 0x76 || opcode == 0x79 || opcode == 0x7a;
|
||||
const bool registerWrite = opcode == 0x69 || opcode == 0x76 || opcode == 0x79 || opcode == 0x7a || (opcode == 0x37 && ((packet[1] >> 8u) & 0xfu) == 0);
|
||||
auto allowedFlags = opcode == 0x11 || opcode == 0x15 || opcode == 0x16 ? 2u : registerWrite ? 6u : opcode == 0x3c || opcode == 0x93 ? 2u : 0u;
|
||||
if (opcode != 0x20 && opcode != 0x22) allowedFlags |= 1u;
|
||||
if ((flags & ~allowedFlags) != 0) throw std::runtime_error("PM4 header flags 0x" + ToHex(flags) + " are not implemented");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/ShaderDeviceProfile.hpp"
|
||||
#include "BdaAbi.hpp"
|
||||
#include "CacheKey.hpp"
|
||||
#include <spirv/unified1/spirv.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -75,6 +76,7 @@ ShaderDeviceProfile::ShaderDeviceProfile(const ShaderRecompiler::SpirvTarget& ta
|
||||
Require(!target.mesh || meshEnabled, "shader device profile exposes disabled mesh shaders");
|
||||
Require(!target.nonConstantImageOffsets || (maintenance8 != nullptr && maintenance8->maintenance8 == VK_TRUE), "shader device profile exposes disabled maintenance8");
|
||||
Require(!target.tessellation || core.tessellationShader == VK_TRUE, "shader device profile exposes disabled tessellation");
|
||||
Require(!target.shaderImageMinLod || core.shaderResourceMinLod == VK_TRUE, "shader device profile exposes a disabled shaderResourceMinLod");
|
||||
for (const auto extension : target.supportedExtensions) extensions.emplace_back(extension);
|
||||
std::ranges::sort(extensions);
|
||||
extensions.erase(std::unique(extensions.begin(), extensions.end()), extensions.end());
|
||||
@@ -83,6 +85,7 @@ ShaderDeviceProfile::ShaderDeviceProfile(const ShaderRecompiler::SpirvTarget& ta
|
||||
Require(std::ranges::find(extensionViews, "SPV_KHR_terminate_invocation") == extensionViews.end() || (terminate != nullptr && terminate->shaderTerminateInvocation == VK_TRUE), "shader device profile advertises a disabled feature: shaderTerminateInvocation");
|
||||
this->target.supportedCapabilities = capabilities;
|
||||
this->target.supportedExtensions = extensionViews;
|
||||
ShaderRecompiler::RecompileCacheKey::SealFeatureDigest(this->target);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,10 +2,15 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/ShaderMemory.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
|
||||
#include "prx/libc/include/GuestAllocations.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/GuestTextureResource.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/TextureTiling.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/TextureFormat.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/TextureSwizzleEquations.hpp"
|
||||
#include "prx/libc/include/HostThreadLocal.hpp"
|
||||
#include "Optimization/RequestMemoryView.hpp"
|
||||
#include "Optimization/ResourceMaterializer.hpp"
|
||||
#include "Optimization/ResourceProgram.hpp"
|
||||
#include "Optimization/SrtWalker.hpp"
|
||||
#include "ThreadOwned.hpp"
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
@@ -35,6 +40,8 @@ struct CaptureProfile {
|
||||
// were read raw on the driver's evidence, or were read both ways (verify) and differed.
|
||||
std::atomic<std::uint64_t> pagesWordwise{0};
|
||||
std::atomic<std::uint64_t> wordWaits{0};
|
||||
std::atomic<std::uint64_t> branchReadsRefused{0};
|
||||
std::atomic<std::uint64_t> branchCapturesRedone{0};
|
||||
std::atomic<std::uint64_t> wordWaitNanoseconds{0};
|
||||
std::atomic<std::uint64_t> wordsRaw{0};
|
||||
std::atomic<std::uint64_t> wordsVerified{0};
|
||||
@@ -69,6 +76,55 @@ struct CaptureProfile {
|
||||
|
||||
constexpr std::uint64_t WordWaitNanoseconds = 50000;
|
||||
|
||||
std::uint64_t imageViewGeneration(void*) {
|
||||
return GuestAllocations::GuestAllocationsGeneration_nid_postfix();
|
||||
}
|
||||
|
||||
bool normalizeImageView(void*, std::uint32_t maxArrayLayers, std::array<std::uint32_t, 8>& descriptor, ShaderRecompiler::SrtImageViewIdentity& identity) {
|
||||
identity.generation = GuestAllocations::GuestAllocationsGeneration_nid_postfix();
|
||||
if (((descriptor[3] >> 28u) & 0xfu) != 12u) return false;
|
||||
const auto resource = Graphics::DecodeTextureResource(descriptor);
|
||||
identity.address = resource.baseAddress;
|
||||
const auto range = GuestAllocations::GuestAllocationsLookup_nid_postfix(static_cast<std::uintptr_t>(resource.baseAddress), false);
|
||||
if (range != nullptr) {
|
||||
identity.hasRange = true;
|
||||
identity.readable = range->readable;
|
||||
identity.writable = range->writable;
|
||||
identity.gpu = range->gpu;
|
||||
identity.rangeAddress = range->address;
|
||||
identity.rangeBytes = range->bytes;
|
||||
identity.allocationAddress = range->allocationAddress;
|
||||
identity.allocationBytes = range->allocationBytes;
|
||||
identity.backingSerial = range->backingSerial;
|
||||
}
|
||||
if (maxArrayLayers == 0u || resource.dimension != Graphics::TextureDimension::k1DArray || range == nullptr) return false;
|
||||
const auto rawCount = resource.depthOrLastArray >= resource.baseArray ? resource.depthOrLastArray - resource.baseArray + 1u : 0u;
|
||||
const auto geometry = Graphics::DescribeSurface(resource);
|
||||
if (geometry.layerBytes == 0u || geometry.thick || geometry.layers != resource.depthOrLastArray + 1u) return false;
|
||||
if (const auto xorMode = Graphics::XorSwizzleMode(resource.tileMode); xorMode != 0u) {
|
||||
const auto* equation = Graphics::FindTextureSwizzleEquation(xorMode, Graphics::BytesPerElement(resource.format));
|
||||
if (equation == nullptr || std::any_of(equation->bits.begin(), equation->bits.end(), [](std::uint32_t bit) { return (bit & 0xff000000u) != 0u; })) return false;
|
||||
}
|
||||
if (!range->readable || !range->gpu || range->bytes == 0u || range->address > std::numeric_limits<std::uint64_t>::max() - range->bytes || range->allocationAddress > std::numeric_limits<std::uint64_t>::max() - range->allocationBytes) return false;
|
||||
const auto rangeEnd = range->address + range->bytes;
|
||||
const auto allocationEnd = range->allocationAddress + range->allocationBytes;
|
||||
if (resource.baseAddress < range->address || resource.baseAddress > rangeEnd || range->address < range->allocationAddress || rangeEnd > allocationEnd) return false;
|
||||
const auto offset = resource.baseAddress - range->address;
|
||||
if (offset % geometry.layerBytes != 0u) return false;
|
||||
const auto coveredBytes = rangeEnd - resource.baseAddress;
|
||||
if (coveredBytes % geometry.layerBytes != 0u) return false;
|
||||
const auto completeSlices = coveredBytes / geometry.layerBytes;
|
||||
if (completeSlices <= resource.baseArray) return false;
|
||||
if (rawCount <= maxArrayLayers) return false;
|
||||
const auto available = completeSlices - resource.baseArray;
|
||||
const auto effectiveCount = std::min<std::uint64_t>(rawCount, available);
|
||||
if (effectiveCount == 0u || effectiveCount == rawCount) return false;
|
||||
const auto lastArray = static_cast<std::uint64_t>(resource.baseArray) + effectiveCount - 1u;
|
||||
if (lastArray > 0x1fffu) return false;
|
||||
descriptor[4] = (descriptor[4] & ~0x1fffu) | static_cast<std::uint32_t>(lastArray);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WordwisePages() {
|
||||
static const bool wordwise = std::getenv("APS5_NO_WORDWISE_CAPTURE") == nullptr;
|
||||
return wordwise;
|
||||
@@ -94,6 +150,11 @@ CaptureProfile& CaptureTotals() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
bool BranchesSkipPendingWords() {
|
||||
static const bool skip = std::getenv("APS5_WAIT_PENDING_BRANCHES") == nullptr;
|
||||
return skip;
|
||||
}
|
||||
|
||||
std::atomic<ShaderMemory::WaitedMsProvider> waitedMsProvider{nullptr};
|
||||
|
||||
double WaitedMs() {
|
||||
@@ -372,6 +433,10 @@ bool ShaderMemory::read(void* context, std::uint64_t address, std::uint32_t* val
|
||||
waited = page.wordwise && (self.hookWaits != nullptr ? self.hookWaits() != waitsBefore : true);
|
||||
word = verifiedWord;
|
||||
}
|
||||
} else if (page.wordwise && policy == PendingWrite::Sync && !forcedRaw && !self.waitBranches && BranchesSkipPendingWords() && ShaderRecompiler::SrtEvaluatingBranch()) {
|
||||
++self.branchReadsRefused;
|
||||
if (CaptureProfiled()) ++CaptureTotals().branchReadsRefused;
|
||||
return false;
|
||||
} else {
|
||||
// On a word-wise page the bytes before the hook's wait are kept for the observer.
|
||||
const bool observed = page.wordwise && policy == PendingWrite::Sync && self.observe != nullptr && GuestMemory::Accessible(reinterpret_cast<const void*>(address), sizeof(word));
|
||||
@@ -722,11 +787,29 @@ std::vector<std::shared_ptr<const ShaderRecompiler::SrtGuestWords>> ShaderMemory
|
||||
}
|
||||
|
||||
std::shared_ptr<const ShaderRecompiler::ResourceCapture> ShaderMemory::Capture(const ShaderRecompiler::RecompileRequest& request, const ShaderRecompiler::SourceHandle* handle) {
|
||||
return capture(request, handle, nullptr);
|
||||
return captureWaitingOnFailure(request, handle, nullptr);
|
||||
}
|
||||
|
||||
std::shared_ptr<const ShaderRecompiler::ResourceCapture> ShaderMemory::Capture(const ShaderRecompiler::PreparedShaderInvocation& invocation) {
|
||||
return capture(invocation.Request(), nullptr, &invocation);
|
||||
return captureWaitingOnFailure(invocation.Request(), nullptr, &invocation);
|
||||
}
|
||||
|
||||
std::shared_ptr<const ShaderRecompiler::ResourceCapture> ShaderMemory::captureWaitingOnFailure(const ShaderRecompiler::RecompileRequest& request, const ShaderRecompiler::SourceHandle* handle, const ShaderRecompiler::PreparedShaderInvocation* invocation) {
|
||||
branchReadsRefused = 0;
|
||||
try {
|
||||
return capture(request, handle, invocation);
|
||||
} catch (const std::exception&) {
|
||||
if (branchReadsRefused == 0u) throw;
|
||||
}
|
||||
if (CaptureProfiled()) ++CaptureTotals().branchCapturesRedone;
|
||||
struct WaitBranches {
|
||||
bool& wait;
|
||||
explicit WaitBranches(bool& flag) : wait(flag) { wait = true; }
|
||||
~WaitBranches() { wait = false; }
|
||||
WaitBranches(const WaitBranches&) = delete;
|
||||
WaitBranches& operator=(const WaitBranches&) = delete;
|
||||
} waiting(waitBranches);
|
||||
return capture(request, handle, invocation);
|
||||
}
|
||||
|
||||
std::shared_ptr<const ShaderRecompiler::ResourceCapture> ShaderMemory::capture(const ShaderRecompiler::RecompileRequest& request, const ShaderRecompiler::SourceHandle* handle, const ShaderRecompiler::PreparedShaderInvocation* invocation) {
|
||||
@@ -750,6 +833,8 @@ std::shared_ptr<const ShaderRecompiler::ResourceCapture> ShaderMemory::capture(c
|
||||
runtime.unchangedSince = &unchangedSince;
|
||||
runtime.supplyWords = &supplyWords;
|
||||
runtime.descriptorScope = &descriptorScope;
|
||||
runtime.normalizeImageView = &normalizeImageView;
|
||||
runtime.imageViewGeneration = &imageViewGeneration;
|
||||
auto capture = invocation != nullptr ? invocation->Capture(runtime) : handle != nullptr ? ShaderRecompiler::CaptureResources(request, runtime, *handle) : ShaderRecompiler::CaptureResources(request, runtime);
|
||||
if (profile) {
|
||||
totals.captureNanoseconds += NanosecondsSince(started);
|
||||
@@ -772,7 +857,7 @@ std::shared_ptr<const ShaderRecompiler::ResourceCapture> ShaderMemory::capture(c
|
||||
const auto materializeNs = ShaderRecompiler::ResourceMaterializer::MaterializeNanoseconds();
|
||||
const auto evaluateNs = ShaderRecompiler::ResourceMaterializer::EvaluateNanoseconds();
|
||||
const auto walkNs = captureNs > resolveNs + pageNs + wordNs + specializationNs ? captureNs - resolveNs - pageNs - wordNs - specializationNs : 0;
|
||||
AgcDriver::ProfilePrint_nid_no_patch( "[capture] %llu captures: %llu word reads, %llu pages fetched (%llu read word by word over pending GPU writes: %llu words waited %.2f s, %llu read raw on evidence, %llu verified with %llu mismatches, %llu served from known values, %llu hook reads not observed: no GPU wait), capture (plan lookup + materialize) %.1f s, %llu KiB registered code this capture; sub-phases (s, us per capture): source resolve %.2f/%.1f, walk %.2f/%.1f, specialization (every materialize) %.2f/%.1f, page reads %.2f/%.1f, word reads %.2f/%.1f, hook GPU waits inside %.2f/%.1f, materialize %.2f/%.1f (SRT evaluate %.2f/%.1f); source handle memo %llu hits, %llu resolves\n", static_cast<unsigned long long>(totals.captures.load()), static_cast<unsigned long long>(totals.reads.load()), static_cast<unsigned long long>(totals.pages.load()), static_cast<unsigned long long>(totals.pagesWordwise.load()), static_cast<unsigned long long>(totals.wordWaits.load()), totals.wordWaitNanoseconds.load() / 1e9, static_cast<unsigned long long>(totals.wordsRaw.load()), static_cast<unsigned long long>(totals.wordsVerified.load()), static_cast<unsigned long long>(totals.wordMismatches.load()), static_cast<unsigned long long>(totals.wordsKnown.load()), static_cast<unsigned long long>(totals.observationsSkipped.load()), captureNs / 1e9, static_cast<unsigned long long>(initialBytes / 1024), resolveNs / 1e9, resolveNs / captures / 1e3, walkNs / 1e9, walkNs / captures / 1e3, specializationNs / 1e9, specializationNs / captures / 1e3, pageNs / 1e9, pageNs / captures / 1e3, wordNs / 1e9, wordNs / captures / 1e3, hookNs / 1e9, hookNs / captures / 1e3, materializeNs / 1e9, materializeNs / captures / 1e3, evaluateNs / 1e9, evaluateNs / captures / 1e3, static_cast<unsigned long long>(totals.handleHits.load()), static_cast<unsigned long long>(totals.handleMisses.load()));
|
||||
AgcDriver::ProfilePrint_nid_no_patch( "[capture] %llu captures: %llu word reads, %llu pages fetched (%llu read word by word over pending GPU writes: %llu words waited %.2f s, %llu read raw on evidence, %llu verified with %llu mismatches, %llu served from known values, %llu hook reads not observed: no GPU wait, %llu branch condition reads over pending GPU writes left the branch unpruned instead of waiting, %llu captures redone waiting after one failed), capture (plan lookup + materialize) %.1f s, %llu KiB registered code this capture; sub-phases (s, us per capture): source resolve %.2f/%.1f, walk %.2f/%.1f, specialization (every materialize) %.2f/%.1f, page reads %.2f/%.1f, word reads %.2f/%.1f, hook GPU waits inside %.2f/%.1f, materialize %.2f/%.1f (SRT evaluate %.2f/%.1f); source handle memo %llu hits, %llu resolves\n", static_cast<unsigned long long>(totals.captures.load()), static_cast<unsigned long long>(totals.reads.load()), static_cast<unsigned long long>(totals.pages.load()), static_cast<unsigned long long>(totals.pagesWordwise.load()), static_cast<unsigned long long>(totals.wordWaits.load()), totals.wordWaitNanoseconds.load() / 1e9, static_cast<unsigned long long>(totals.wordsRaw.load()), static_cast<unsigned long long>(totals.wordsVerified.load()), static_cast<unsigned long long>(totals.wordMismatches.load()), static_cast<unsigned long long>(totals.wordsKnown.load()), static_cast<unsigned long long>(totals.observationsSkipped.load()), static_cast<unsigned long long>(totals.branchReadsRefused.load()), static_cast<unsigned long long>(totals.branchCapturesRedone.load()), captureNs / 1e9, static_cast<unsigned long long>(initialBytes / 1024), resolveNs / 1e9, resolveNs / captures / 1e3, walkNs / 1e9, walkNs / captures / 1e3, specializationNs / 1e9, specializationNs / captures / 1e3, pageNs / 1e9, pageNs / captures / 1e3, wordNs / 1e9, wordNs / captures / 1e3, hookNs / 1e9, hookNs / captures / 1e3, materializeNs / 1e9, materializeNs / captures / 1e3, evaluateNs / 1e9, evaluateNs / captures / 1e3, static_cast<unsigned long long>(totals.handleHits.load()), static_cast<unsigned long long>(totals.handleMisses.load()));
|
||||
}
|
||||
}
|
||||
return capture;
|
||||
|
||||
@@ -368,6 +368,51 @@ struct WorkgroupMemory {
|
||||
}
|
||||
};
|
||||
|
||||
struct ScratchPool {
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
PFN_vkDestroyDescriptorPool destroyPool = nullptr;
|
||||
std::unique_ptr<Graphics::DeviceBuffer> buffer;
|
||||
VkDescriptorPool pool = VK_NULL_HANDLE;
|
||||
VkDescriptorSet set = VK_NULL_HANDLE;
|
||||
std::uint64_t slots = 0;
|
||||
std::uint64_t headerBytes = 0;
|
||||
std::uint64_t bytes = 0;
|
||||
std::uint64_t lastUse = 0;
|
||||
~ScratchPool() {
|
||||
buffer.reset();
|
||||
if (pool != VK_NULL_HANDLE) destroyPool(device, pool, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
void ZeroScratchPoolHeader(const Graphics::Context& context, const ScratchPool& pool) {
|
||||
Graphics::CommandBatch batch(context);
|
||||
context.Resolved(&Graphics::DeviceFunctions::cmdFillBuffer, "vkCmdFillBuffer")(batch.Handle(), pool.buffer->Handle(), 0, pool.headerBytes, 0u);
|
||||
Graphics::RecordMemoryBarrier(context, batch.Handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
|
||||
batch.SubmitAndWait();
|
||||
}
|
||||
|
||||
std::uint64_t MebibytesFromEnvironment(const char* name, std::uint64_t fallback) {
|
||||
std::uint64_t mebibytes = fallback;
|
||||
if (const char* text = std::getenv(name)) {
|
||||
char* end = nullptr;
|
||||
const auto parsed = std::strtoull(text, &end, 10);
|
||||
if (end != text && *end == 0 && parsed != 0) mebibytes = parsed;
|
||||
}
|
||||
return mebibytes << 20u;
|
||||
}
|
||||
|
||||
std::uint64_t ScratchPoolCapBytes() {
|
||||
static const std::uint64_t bytes = MebibytesFromEnvironment("APS5_SCRATCH_POOL_MIB", 64);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
constexpr std::uint64_t ScratchPoolBufferLimit = std::uint64_t{1} << 31u;
|
||||
|
||||
std::uint64_t ScratchPoolTotalBytes() {
|
||||
static const std::uint64_t bytes = MebibytesFromEnvironment("APS5_SCRATCH_POOL_TOTAL_MIB", 256);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
struct VulkanDevice::State {
|
||||
bool compileOnly = false;
|
||||
void* library = nullptr;
|
||||
@@ -424,6 +469,7 @@ struct VulkanDevice::State {
|
||||
bool shaderTerminateInvocation = false;
|
||||
bool fusedExactArithmetic = false;
|
||||
bool fragmentBarycentricBuiltins = false;
|
||||
bool hostInterpolationFirst = false;
|
||||
bool geometryShader = false;
|
||||
bool largePoints = false;
|
||||
bool sampleRateShading = false;
|
||||
@@ -464,8 +510,11 @@ struct VulkanDevice::State {
|
||||
bool graphicsPipelineLibrary = false;
|
||||
bool pipelineLinkTimeOptimization = true;
|
||||
bool imageViewMinLod = false;
|
||||
bool shaderResourceMinLod = false;
|
||||
bool shaderImageMinLod = false;
|
||||
bool pipelineExecutableInfo = false;
|
||||
bool maintenance8 = false;
|
||||
bool pushDescriptors = false;
|
||||
bool maintenance5 = false;
|
||||
bool fillModeNonSolid = false;
|
||||
std::uint32_t srgbDecodeFormats = 0;
|
||||
@@ -536,6 +585,9 @@ struct VulkanDevice::State {
|
||||
std::vector<std::pair<std::array<std::uint32_t, 4>, std::shared_ptr<Graphics::DeviceBuffer>>> patternBuffers;
|
||||
VkDescriptorSetLayout workgroupMemoryLayout = VK_NULL_HANDLE;
|
||||
std::shared_ptr<WorkgroupMemory> workgroupMemory;
|
||||
std::mutex scratchPoolsMutex;
|
||||
std::map<ShaderRecompiler::PipelineIdentity, std::shared_ptr<ScratchPool>> scratchPools;
|
||||
std::uint64_t scratchPoolUses = 0;
|
||||
// Compute pipeline objects by variant (and push-constant use), under their own mutex: the
|
||||
// dispatch's find-or-insert and the verify switch's lookups touch the map, recipes hold weak
|
||||
// references to its objects.
|
||||
@@ -554,6 +606,7 @@ struct VulkanDevice::State {
|
||||
std::unique_ptr<Graphics::PipelineCache> pipelineCache;
|
||||
std::unique_ptr<Graphics::DescriptorCache> descriptorCache;
|
||||
std::unique_ptr<Graphics::VertexInputCache> vertexInputs;
|
||||
Graphics::VertexBufferFormats vertexFormats;
|
||||
std::unique_ptr<Graphics::SamplerCache> samplerCache;
|
||||
Graphics::ResourceCache& resourceCache = Graphics::SharedResourceCache();
|
||||
// Recorded dispatches that write a copied buffer (their results reach guest memory by a CPU
|
||||
@@ -699,6 +752,65 @@ struct VulkanDevice::State {
|
||||
return workgroupMemory;
|
||||
}
|
||||
|
||||
std::shared_ptr<ScratchPool> ScratchPoolFor(const Graphics::Context& context, const ShaderRecompiler::PipelineIdentity& identity, std::uint32_t slotDwords, std::uint64_t groups) {
|
||||
const auto range = std::min<std::uint64_t>(properties.limits.maxStorageBufferRange, ScratchPoolBufferLimit);
|
||||
const auto slotBytes = (static_cast<std::uint64_t>(slotDwords) + 2u) * 4u;
|
||||
if (slotBytes > range) {
|
||||
throw std::runtime_error("Vulkan dispatch: one scratch pool slot of " + std::to_string(slotBytes) + " bytes is over the scratch pool buffer limit of " + std::to_string(range) + " bytes");
|
||||
}
|
||||
const auto capSlots = std::max<std::uint64_t>(std::min({ScratchPoolCapBytes(), ScratchPoolTotalBytes(), range}) / slotBytes, 1u);
|
||||
const auto wanted = std::clamp<std::uint64_t>(groups, 1u, capSlots);
|
||||
std::lock_guard lock(scratchPoolsMutex);
|
||||
const auto use = ++scratchPoolUses;
|
||||
if (const auto found = scratchPools.find(identity); found != scratchPools.end() && found->second->slots >= wanted) {
|
||||
found->second->lastUse = use;
|
||||
return found->second;
|
||||
}
|
||||
const auto size = wanted * slotBytes;
|
||||
EvictScratchPools(identity, size);
|
||||
auto created = std::make_shared<ScratchPool>();
|
||||
created->device = device;
|
||||
created->destroyPool = DeviceFunction<PFN_vkDestroyDescriptorPool>("vkDestroyDescriptorPool");
|
||||
created->slots = wanted;
|
||||
created->headerBytes = wanted * 2u * 4u;
|
||||
created->bytes = size;
|
||||
created->lastUse = use;
|
||||
created->buffer = std::make_unique<Graphics::DeviceBuffer>(context, static_cast<std::size_t>(size), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
const VkDescriptorPoolSize poolSize{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1};
|
||||
VkDescriptorPoolCreateInfo poolInfo{VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
|
||||
poolInfo.maxSets = 1;
|
||||
poolInfo.poolSizeCount = 1;
|
||||
poolInfo.pPoolSizes = &poolSize;
|
||||
check(DeviceFunction<PFN_vkCreateDescriptorPool>("vkCreateDescriptorPool")(device, &poolInfo, nullptr, &created->pool), "vkCreateDescriptorPool scratch pool");
|
||||
VkDescriptorSetAllocateInfo allocation{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO};
|
||||
allocation.descriptorPool = created->pool;
|
||||
allocation.descriptorSetCount = 1;
|
||||
allocation.pSetLayouts = &workgroupMemoryLayout;
|
||||
check(DeviceFunction<PFN_vkAllocateDescriptorSets>("vkAllocateDescriptorSets")(device, &allocation, &created->set), "vkAllocateDescriptorSets scratch pool");
|
||||
const VkDescriptorBufferInfo described{created->buffer->Handle(), 0, size};
|
||||
VkWriteDescriptorSet write{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET};
|
||||
write.dstSet = created->set;
|
||||
write.dstBinding = 0;
|
||||
write.descriptorCount = 1;
|
||||
write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
write.pBufferInfo = &described;
|
||||
DeviceFunction<PFN_vkUpdateDescriptorSets>("vkUpdateDescriptorSets")(device, 1, &write, 0, nullptr);
|
||||
ZeroScratchPoolHeader(context, *created);
|
||||
scratchPools[identity] = created;
|
||||
return created;
|
||||
}
|
||||
|
||||
void EvictScratchPools(const ShaderRecompiler::PipelineIdentity& identity, std::uint64_t needed) {
|
||||
scratchPools.erase(identity);
|
||||
std::uint64_t held = 0;
|
||||
for (const auto& [key, pool] : scratchPools) held += pool->bytes;
|
||||
while (!scratchPools.empty() && held + needed > ScratchPoolTotalBytes()) {
|
||||
const auto oldest = std::min_element(scratchPools.begin(), scratchPools.end(), [](const auto& left, const auto& right) { return left.second->lastUse < right.second->lastUse; });
|
||||
held -= oldest->second->bytes;
|
||||
scratchPools.erase(oldest);
|
||||
}
|
||||
}
|
||||
|
||||
void CreateMarkerBuffer() {
|
||||
bufferMarker = DeviceFunction<PFN_vkCmdWriteBufferMarkerAMD>("vkCmdWriteBufferMarkerAMD");
|
||||
VkBufferCreateInfo buffer{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
|
||||
@@ -960,6 +1072,7 @@ struct VulkanDevice::State {
|
||||
Graphics::ClearHostImports(device);
|
||||
patternBuffers.clear();
|
||||
workgroupMemory.reset();
|
||||
scratchPools.clear();
|
||||
if (workgroupMemoryLayout != VK_NULL_HANDLE) reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(deviceProc(device, "vkDestroyDescriptorSetLayout"))(device, workgroupMemoryLayout, nullptr);
|
||||
descriptorCache.reset();
|
||||
vertexInputs.reset();
|
||||
@@ -1362,6 +1475,8 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
|
||||
state->individuallyFreeDescriptorSets = driver.driverID == VK_DRIVER_ID_MESA_LLVMPIPE;
|
||||
state->fusedExactArithmetic = driver.driverID == VK_DRIVER_ID_MOLTENVK;
|
||||
state->tessellationPipelineCache = TessellationPipelineCacheUsable(driver.driverID);
|
||||
state->hostInterpolationFirst = HostInterpolationPreferred(driver.driverID) && std::getenv("APS5_NO_HOST_INTERPOLATION_FIRST") == nullptr;
|
||||
APS5_LOG_OUT("Pixel interpolation driver=%d hostInterpolationFirst=%d", static_cast<int>(driver.driverID), state->hostInterpolationFirst ? 1 : 0);
|
||||
state->subgroupControlBarriers = SubgroupControlBarrierUsable(driver.driverID);
|
||||
state->workgroupScopeFences = WorkgroupScopeFenceUsable(driver.driverID);
|
||||
state->ldsLockFences = LdsLockFencesRequired(driver.driverID);
|
||||
@@ -1633,6 +1748,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
|
||||
state->drawInputsInPlace = std::getenv("APS5_NO_DRAW_INPUTS_IN_PLACE") == nullptr && (std::getenv("APS5_DRAW_INPUTS_IN_PLACE") != nullptr || DrawInputsInPlaceUsable(driverProperties.driverID, windows));
|
||||
if (!compileOnly) Graphics::SetHostImportWindow(8ull << 20u);
|
||||
if (!compileOnly) Graphics::SetHostImportMaxBytes(maintenance3.maxMemoryAllocationSize);
|
||||
if (!compileOnly) Pm4::RequestImportableGds(state->properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
|
||||
#ifdef _WIN32
|
||||
// Imported pages are locked; locking is bounded by the process working-set minimum.
|
||||
if (const char* value = std::getenv("APS5_WORKING_SET_MIB"); value != nullptr && !compileOnly) {
|
||||
@@ -1677,7 +1793,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
|
||||
if (hasExtension(VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME)) {
|
||||
VkPhysicalDeviceFeatures2 features{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &minLodFeatures};
|
||||
state->InstanceFunction<PFN_vkGetPhysicalDeviceFeatures2>("vkGetPhysicalDeviceFeatures2")(selected, &features);
|
||||
state->imageViewMinLod = minLodFeatures.minLod == VK_TRUE;
|
||||
state->imageViewMinLod = minLodFeatures.minLod == VK_TRUE && std::getenv("APS5_NO_IMAGE_VIEW_MIN_LOD") == nullptr;
|
||||
if (state->imageViewMinLod) deviceExtensions.push_back(VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME);
|
||||
}
|
||||
minLodFeatures = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT};
|
||||
@@ -1691,6 +1807,8 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
|
||||
}
|
||||
maintenance8Features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_8_FEATURES_KHR};
|
||||
maintenance8Features.maintenance8 = VK_TRUE;
|
||||
state->pushDescriptors = hasExtension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
if (state->pushDescriptors) deviceExtensions.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
VkPhysicalDeviceDepthClipControlFeaturesEXT depthClipFeatures{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT};
|
||||
if (hasExtension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME)) {
|
||||
VkPhysicalDeviceFeatures2 features{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &depthClipFeatures};
|
||||
@@ -1896,6 +2014,8 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
|
||||
if (enabled.shaderImageGatherExtended) state->capabilities.push_back(spv::CapabilityImageGatherExtended);
|
||||
enabled.shaderResourceMinLod = available.shaderResourceMinLod;
|
||||
if (enabled.shaderResourceMinLod) state->capabilities.push_back(spv::CapabilityMinLod);
|
||||
state->shaderResourceMinLod = enabled.shaderResourceMinLod == VK_TRUE;
|
||||
state->shaderImageMinLod = state->shaderResourceMinLod && !state->imageViewMinLod && !state->graphicsPipelineLibrary;
|
||||
enabled.sampleRateShading = available.sampleRateShading;
|
||||
enabled.geometryShader = available.geometryShader;
|
||||
state->geometryShader = enabled.geometryShader == VK_TRUE;
|
||||
@@ -2203,12 +2323,13 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
|
||||
if (domains(selected, &domainCount, available.data()) != VK_SUCCESS) available.clear();
|
||||
}
|
||||
#ifdef _WIN32
|
||||
const auto host = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR;
|
||||
const std::array hosts{VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR};
|
||||
#else
|
||||
const auto host = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR;
|
||||
const std::array hosts{VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR, VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR};
|
||||
#endif
|
||||
if (std::ranges::find(available, VK_TIME_DOMAIN_DEVICE_KHR) != available.end() && std::ranges::find(available, host) != available.end()) {
|
||||
state->hostTimeDomain = host;
|
||||
const auto host = std::ranges::find_first_of(hosts, available);
|
||||
if (std::ranges::find(available, VK_TIME_DOMAIN_DEVICE_KHR) != available.end() && host != hosts.end()) {
|
||||
state->hostTimeDomain = *host;
|
||||
state->calibratedTimestamps = state->DeviceFunction<PFN_vkGetCalibratedTimestampsKHR>(khr ? "vkGetCalibratedTimestampsKHR" : "vkGetCalibratedTimestampsEXT");
|
||||
}
|
||||
}
|
||||
@@ -2257,6 +2378,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
|
||||
Graphics::PrepareImportWatch(graphicsContext());
|
||||
state->bufferPool = std::make_shared<Graphics::BufferPool>(graphicsContext());
|
||||
state->emptyBuffer = std::make_unique<Graphics::Buffer>(graphicsContext(), Graphics::EmptyBufferBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
if (!compileOnly && Pm4::GdsImportable() && Graphics::HostImportFor(graphicsContext(), Pm4::GdsAddress(), Pm4::GdsBytes, Graphics::ImportRequester::Map) == nullptr) Pm4::RejectGdsImport();
|
||||
state->pipelineCache = std::make_unique<Graphics::PipelineCache>(graphicsContext(), state->properties, window != nullptr || compileOnly);
|
||||
state->detiler = std::make_unique<Graphics::TextureDetiler>(graphicsContext());
|
||||
state->textureCache = std::make_unique<Graphics::TextureCache>(graphicsContext());
|
||||
@@ -2592,7 +2714,7 @@ int VulkanDevice::WriteLabelOnGpu(std::uint64_t address, std::span<const std::by
|
||||
static const bool storeAtLabel = Graphics::StorageTexture::StoreAtLabelRequested(std::getenv("APS5_STORE_AT_LABEL"));
|
||||
if (storeAtLabel) Graphics::StorageTexture::FlushAllPending("label", state->device);
|
||||
if (queue == 0) static_cast<void>(Graphics::StorageTexture::StoreDrawnLinear("label"));
|
||||
Graphics::StorageTexture::StoreReadbackBeforeLabel("readback before label");
|
||||
Graphics::StorageTexture::StoreReadbackBeforeLabel("readback before label", state->device);
|
||||
if (!state->recorder || bytes.empty() || bytes.size() > 65536 || address % 4 != 0 || bytes.size() % 4 != 0) return 4;
|
||||
auto& recorder = *state->recorder;
|
||||
// Batches that already finished are retired before the checks: their completions ran, so they
|
||||
@@ -4123,7 +4245,7 @@ bool VulkanDevice::CalibrateClock(double& gpuNs, std::chrono::steady_clock::time
|
||||
const double sinceNs = static_cast<double>(static_cast<std::uint64_t>(counter.QuadPart) - stamps[1]) * 1e9 / static_cast<double>(frequency.QuadPart);
|
||||
#else
|
||||
timespec monotonic{};
|
||||
clock_gettime(CLOCK_MONOTONIC, &monotonic);
|
||||
clock_gettime(state->hostTimeDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR ? CLOCK_MONOTONIC_RAW : CLOCK_MONOTONIC, &monotonic);
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const double sinceNs = static_cast<double>(static_cast<std::uint64_t>(monotonic.tv_sec) * 1000000000ull + static_cast<std::uint64_t>(monotonic.tv_nsec) - stamps[1]);
|
||||
#endif
|
||||
@@ -4151,6 +4273,7 @@ ShaderRecompiler::SpirvTarget VulkanDevice::Target() const {
|
||||
auto target = state->shaderProfile->Target();
|
||||
target.float32FlushToZero = state->float32FlushToZero;
|
||||
target.fusedExactArithmetic = state->fusedExactArithmetic;
|
||||
target.hostInterpolationFirst = state->hostInterpolationFirst;
|
||||
target.float32DenormPreserve = state->float32DenormPreserve;
|
||||
return target;
|
||||
}
|
||||
@@ -4166,6 +4289,7 @@ ShaderRecompiler::SpirvTarget VulkanDevice::buildTarget() const {
|
||||
target.fragmentShaderBarycentricEnabled = state->fragmentShaderBarycentric;
|
||||
target.fragmentBarycentricBuiltins = state->fragmentBarycentricBuiltins;
|
||||
target.nonConstantImageOffsets = state->maintenance8;
|
||||
target.shaderImageMinLod = state->shaderImageMinLod;
|
||||
target.narrowSubgroupClock = state->narrowSubgroupClock;
|
||||
target.float64DenormPreserve = state->float64DenormPreserve;
|
||||
target.float16DenormPreserve = state->float16DenormPreserve;
|
||||
@@ -4182,6 +4306,7 @@ ShaderRecompiler::SpirvTarget VulkanDevice::buildTarget() const {
|
||||
target.ldsLockFences = state->ldsLockFences;
|
||||
target.meshWindowBuffer = state->driverId == VK_DRIVER_ID_NVIDIA_PROPRIETARY && std::getenv("APS5_NO_MESH_WINDOW_BUFFER") == nullptr;
|
||||
target.srgbDecodeFormats = state->srgbDecodeFormats & ~state->srgbCopyFormats;
|
||||
target.maxImageArrayLayers = limits.maxImageArrayLayers;
|
||||
target.vertexSubgroups = (state->subgroup.supportedStages & VK_SHADER_STAGE_VERTEX_BIT) != 0;
|
||||
target.tessellationEvaluationSubgroups = (state->subgroup.supportedStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0;
|
||||
if (state->meshShader) {
|
||||
@@ -4230,6 +4355,13 @@ bool VulkanDevice::GraphicsPipelineLibraries() const {
|
||||
return state->graphicsPipelineLibrary;
|
||||
}
|
||||
|
||||
std::pair<VkBuffer, std::uint64_t> VulkanDevice::scratchPoolHeader(const ShaderRecompiler::RecompileResult& shader) const {
|
||||
std::lock_guard lock(state->scratchPoolsMutex);
|
||||
const auto found = state->scratchPools.find(shader.Identity());
|
||||
if (found == state->scratchPools.end() || found->second == nullptr) return {VK_NULL_HANDLE, 0};
|
||||
return {found->second->buffer->Handle(), found->second->headerBytes};
|
||||
}
|
||||
|
||||
Graphics::Context VulkanDevice::graphicsContext() const {
|
||||
static const bool noCache = std::getenv("APS5_NO_CONTEXT_CACHE") != nullptr;
|
||||
if (state->contextReady && !noCache) return state->context;
|
||||
@@ -4283,6 +4415,7 @@ Graphics::Context VulkanDevice::buildContext() const {
|
||||
context.recorder = state->recorder.get();
|
||||
context.descriptorCache = state->descriptorCache.get();
|
||||
context.vertexInputs = state->vertexInputs.get();
|
||||
context.vertexFormats = &state->vertexFormats;
|
||||
context.samplerCache = state->samplerCache.get();
|
||||
context.drawIndirectFirstInstance = state->drawIndirectFirstInstance;
|
||||
context.multiDrawIndirect = state->multiDrawIndirect;
|
||||
@@ -4339,8 +4472,11 @@ Graphics::Context VulkanDevice::buildContext() const {
|
||||
context.earlyFragmentSampleMaskTestBeforeSampleCounting = state->earlyFragmentSampleMaskTestBeforeSampleCounting;
|
||||
context.primitiveListRestart = state->primitiveListRestart;
|
||||
context.imageViewMinLod = state->imageViewMinLod;
|
||||
context.shaderResourceMinLod = state->shaderResourceMinLod;
|
||||
context.shaderImageMinLod = state->shaderImageMinLod;
|
||||
context.pipelineExecutableInfo = state->pipelineExecutableInfo;
|
||||
context.maintenance8 = state->maintenance8;
|
||||
context.pushDescriptors = state->pushDescriptors;
|
||||
context.srgbDecodeFormats = state->srgbDecodeFormats;
|
||||
context.srgbCopyFormats = state->srgbCopyFormats;
|
||||
context.sampleLocationSampleCounts = state->sampleLocationSampleCounts;
|
||||
@@ -5049,14 +5185,14 @@ VulkanDevice::PresyncStatistics VulkanDevice::PresyncCounts() {
|
||||
return {counters.checked.load(std::memory_order_relaxed), counters.presyncs.load(std::memory_order_relaxed), counters.keyChecks.load(std::memory_order_relaxed), counters.keyWaits.load(std::memory_order_relaxed)};
|
||||
}
|
||||
|
||||
std::shared_ptr<PreparedDispatch> VulkanDevice::PrepareDispatch(const ShaderRecompiler::RecompileResult& shader, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t dispatchThreads, std::uint64_t programAddress, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear) {
|
||||
std::shared_ptr<PreparedDispatch> VulkanDevice::PrepareDispatch(const ShaderRecompiler::RecompileResult& shader, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t dispatchThreads, std::uint64_t programAddress, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear, const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews) {
|
||||
ShaderRecompiler::RuntimeAbi::RequireVersion(shader.runtimeAbiVersion);
|
||||
// APS5_LOCKED_BUILD=1: the whole build under the mutex, as before the split.
|
||||
static const bool lockedBuild = std::getenv("APS5_LOCKED_BUILD") != nullptr;
|
||||
if (lockedBuild || shader.spirv.size() < 5 || shader.spirv[0] != 0x07230203u) return nullptr;
|
||||
static const bool profile = std::getenv("APS5_PROFILE_DRAW") != nullptr;
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
const Graphics::CompiledShader compute{ShaderRecompiler::ShaderStage::Compute, &shader, 0};
|
||||
const Graphics::CompiledShader compute{ShaderRecompiler::ShaderStage::Compute, &shader, 0, registeredImageViews};
|
||||
const auto context = graphicsContext();
|
||||
auto prepared = std::make_shared<PreparedDispatch>();
|
||||
prepared->dispatchThreads = dispatchThreads;
|
||||
@@ -5172,12 +5308,12 @@ std::shared_ptr<RecipeHit> VulkanDevice::PrepareRecipe(const std::shared_ptr<con
|
||||
return hit;
|
||||
}
|
||||
|
||||
void VulkanDevice::Dispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t programAddress, std::shared_ptr<PreparedDispatch> prepared, std::shared_ptr<const Recipe>* recipe, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear) {
|
||||
static_cast<void>(dispatch(shader, x, y, z, 0, snapshots, programAddress, std::move(prepared), recipe, {}, htileClear));
|
||||
void VulkanDevice::Dispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t programAddress, std::shared_ptr<PreparedDispatch> prepared, std::shared_ptr<const Recipe>* recipe, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear, const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews) {
|
||||
static_cast<void>(dispatch(shader, x, y, z, 0, snapshots, programAddress, std::move(prepared), recipe, {}, htileClear, registeredImageViews));
|
||||
}
|
||||
|
||||
VulkanDevice::IndirectOutcome VulkanDevice::DispatchIndirect(const ShaderRecompiler::RecompileResult& shader, std::uint64_t arguments, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t programAddress, std::shared_ptr<PreparedDispatch> prepared, std::shared_ptr<const Recipe>* recipe, const std::array<std::uint32_t, 3>& threadGroup) {
|
||||
return dispatch(shader, 0, 0, 0, arguments, snapshots, programAddress, std::move(prepared), recipe, threadGroup);
|
||||
VulkanDevice::IndirectOutcome VulkanDevice::DispatchIndirect(const ShaderRecompiler::RecompileResult& shader, std::uint64_t arguments, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t programAddress, std::shared_ptr<PreparedDispatch> prepared, std::shared_ptr<const Recipe>* recipe, const std::array<std::uint32_t, 3>& threadGroup, const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews) {
|
||||
return dispatch(shader, 0, 0, 0, arguments, snapshots, programAddress, std::move(prepared), recipe, threadGroup, std::nullopt, registeredImageViews);
|
||||
}
|
||||
|
||||
void VulkanDevice::decideIndirect(RecordedDispatch& record, IndirectOutcome& outcome, char* groupsText) {
|
||||
@@ -5291,6 +5427,11 @@ void VulkanDevice::recordDispatch(RecordedDispatch& record) {
|
||||
if (recorder.HasQueuedKeyStores() && (resources.HoldsLease() || recorder.AnyQueuedKeyStore(touches))) recorder.FlushKeyStores();
|
||||
if (recorder.HasQueuedStores() && (resources.HoldsLease() || recorder.AnyQueuedStore(touches))) recorder.FlushStores();
|
||||
static_cast<void>(Graphics::StorageTexture::StoreDrawnLinearTouching("dispatch access", touches, resources.HoldsLease()));
|
||||
std::shared_ptr<ScratchPool> pool;
|
||||
if (const auto slotDwords = record.shader->program->scratchPoolSlotDwords; slotDwords != 0) {
|
||||
const std::uint64_t groups = argumentImport != nullptr ? std::numeric_limits<std::uint64_t>::max() : static_cast<std::uint64_t>(record.x) * record.y * record.z;
|
||||
pool = state->ScratchPoolFor(context, record.shader->program->Identity(), slotDwords, groups);
|
||||
}
|
||||
bool unordered = false;
|
||||
const auto overlapQueue = Graphics::Recorder::TakeDispatchOrder(unordered);
|
||||
const auto* groupLimit = state->properties.limits.maxComputeWorkGroupCount;
|
||||
@@ -5409,6 +5550,10 @@ void VulkanDevice::recordDispatch(RecordedDispatch& record) {
|
||||
context.Resolved(&Graphics::DeviceFunctions::cmdBindDescriptorSets, "vkCmdBindDescriptorSets")(commands, VK_PIPELINE_BIND_POINT_COMPUTE, record.objects->layout, ShaderRecompiler::WorkgroupMemoryDescriptorSet, 1, &memory->set, 0, nullptr);
|
||||
recorder.Keep(std::move(memory));
|
||||
}
|
||||
if (pool != nullptr) {
|
||||
context.Resolved(&Graphics::DeviceFunctions::cmdBindDescriptorSets, "vkCmdBindDescriptorSets")(commands, VK_PIPELINE_BIND_POINT_COMPUTE, record.objects->layout, ShaderRecompiler::ScratchPoolDescriptorSet, 1, &pool->set, 0, nullptr);
|
||||
recorder.Keep(std::move(pool));
|
||||
}
|
||||
if (record.pushStages != 0) {
|
||||
context.Resolved(&Graphics::DeviceFunctions::cmdPushConstants, "vkCmdPushConstants")(commands, record.objects->layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, Graphics::ComputePushConstantBytes, record.pushBytes->data());
|
||||
}
|
||||
@@ -5507,10 +5652,11 @@ std::shared_ptr<ComputePipelineObjects> VulkanDevice::createComputePipeline(cons
|
||||
objects->destroyPipeline = state->DeviceFunction<PFN_vkDestroyPipeline>("vkDestroyPipeline");
|
||||
objects->module = Graphics::CreateShaderModule(state->DeviceFunction<PFN_vkCreateShaderModule>("vkCreateShaderModule"), state->device, state->graphicsPipelineLibrary, shader.spirv.data(), shader.spirv.size() * sizeof(std::uint32_t), "vkCreateShaderModule");
|
||||
objects->resourcesLayout = setLayout;
|
||||
const std::array<VkDescriptorSetLayout, 2> setLayouts{setLayout, shader.workgroupMemoryDwords != 0 ? state->workgroupMemoryLayout : VK_NULL_HANDLE};
|
||||
const bool scratchPool = shader.scratchPoolSlotDwords != 0;
|
||||
const std::array<VkDescriptorSetLayout, 3> setLayouts{setLayout, shader.workgroupMemoryDwords != 0 || scratchPool ? state->workgroupMemoryLayout : VK_NULL_HANDLE, scratchPool ? state->workgroupMemoryLayout : VK_NULL_HANDLE};
|
||||
const VkPushConstantRange push{VK_SHADER_STAGE_COMPUTE_BIT, 0, Graphics::ComputePushConstantBytes};
|
||||
VkPipelineLayoutCreateInfo layoutInfo{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
|
||||
layoutInfo.setLayoutCount = shader.workgroupMemoryDwords != 0 ? ShaderRecompiler::WorkgroupMemoryDescriptorSet + 1 : 1;
|
||||
layoutInfo.setLayoutCount = scratchPool ? ShaderRecompiler::ScratchPoolDescriptorSet + 1 : shader.workgroupMemoryDwords != 0 ? ShaderRecompiler::WorkgroupMemoryDescriptorSet + 1 : 1;
|
||||
layoutInfo.pSetLayouts = setLayouts.data();
|
||||
layoutInfo.pushConstantRangeCount = pushStages != 0 ? 1 : 0;
|
||||
layoutInfo.pPushConstantRanges = pushStages != 0 ? &push : nullptr;
|
||||
@@ -5530,7 +5676,8 @@ std::shared_ptr<ComputePipelineObjects> VulkanDevice::createComputePipeline(cons
|
||||
resourcesLayout.bindings.push_back({layoutKey[index], type, layoutKey[index + 2u], layoutKey[index + 3u], updateAfterBind && type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ? VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT : 0u});
|
||||
}
|
||||
capture.sets.push_back(std::move(resourcesLayout));
|
||||
if (shader.workgroupMemoryDwords != 0) capture.sets.push_back({0, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, 0}}});
|
||||
if (shader.workgroupMemoryDwords != 0 || scratchPool) capture.sets.push_back({0, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, 0}}});
|
||||
if (scratchPool) capture.sets.push_back({0, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, 0}}});
|
||||
if (pushStages != 0) capture.pushConstants.push_back(push);
|
||||
for (const auto& value : shader.specialization) capture.specialization.push_back({value.id, value.value});
|
||||
capture.requiredSubgroupSize = subgroupSize;
|
||||
@@ -5616,7 +5763,7 @@ std::shared_ptr<ComputePipelineObjects> VulkanDevice::computePipeline(const Grap
|
||||
return finish(std::move(objects), nullptr);
|
||||
}
|
||||
|
||||
VulkanDevice::IndirectOutcome VulkanDevice::dispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::uint64_t arguments, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t programAddress, std::shared_ptr<PreparedDispatch> prepared, std::shared_ptr<const Recipe>* recipeOut, const std::array<std::uint32_t, 3>& threadGroup, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear) {
|
||||
VulkanDevice::IndirectOutcome VulkanDevice::dispatch(const ShaderRecompiler::RecompileResult& shader, std::uint32_t x, std::uint32_t y, std::uint32_t z, std::uint64_t arguments, std::span<const Graphics::GuestMemorySnapshot> snapshots, std::uint64_t programAddress, std::shared_ptr<PreparedDispatch> prepared, std::shared_ptr<const Recipe>* recipeOut, const std::array<std::uint32_t, 3>& threadGroup, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear, const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews) {
|
||||
startJournalReplay();
|
||||
for (const auto& binding : shader.bindings) {
|
||||
if (binding.role != ShaderRecompiler::DescriptorRole::GuestBuffers) continue;
|
||||
@@ -5641,7 +5788,7 @@ VulkanDevice::IndirectOutcome VulkanDevice::dispatch(const ShaderRecompiler::Rec
|
||||
if (shader.spirv.size() < 5 || shader.spirv[0] != 0x07230203u) {
|
||||
throw std::runtime_error("Vulkan dispatch: invalid SPIR-V");
|
||||
}
|
||||
const std::array<Graphics::CompiledShader, 1> shaders{{{ShaderRecompiler::ShaderStage::Compute, &shader, 0}}};
|
||||
const std::array<Graphics::CompiledShader, 1> shaders{{{ShaderRecompiler::ShaderStage::Compute, &shader, 0, registeredImageViews}}};
|
||||
const auto pushStages = Graphics::PushConstantStages(shaders);
|
||||
if (pushStages != 0 && state->properties.limits.maxPushConstantsSize < Graphics::ComputePushConstantBytes) {
|
||||
throw std::runtime_error("Vulkan dispatch: compute push constant range exceeds device limit");
|
||||
|
||||
@@ -26,6 +26,16 @@
|
||||
namespace AgcDriver {
|
||||
|
||||
#ifdef _WIN32
|
||||
bool ReadableStackRegion(std::uint64_t address, std::uint64_t& low, std::uint64_t& high) {
|
||||
constexpr DWORD readable = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
|
||||
MEMORY_BASIC_INFORMATION memory{};
|
||||
if (VirtualQuery(reinterpret_cast<LPCVOID>(address), &memory, sizeof(memory)) == 0 || memory.State != MEM_COMMIT) return false;
|
||||
if ((memory.Protect & (PAGE_GUARD | PAGE_NOACCESS)) != 0 || (memory.Protect & readable) == 0) return false;
|
||||
low = reinterpret_cast<std::uint64_t>(memory.BaseAddress);
|
||||
high = low + memory.RegionSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::jthread processSamplerThread;
|
||||
@@ -72,7 +82,7 @@ struct Sampler {
|
||||
}
|
||||
|
||||
bool readStack(std::uint64_t address, std::uint64_t& value) const {
|
||||
if (address < stackLow || address > stackHigh - sizeof(value)) return false;
|
||||
if (stackHigh < stackLow + sizeof(value) || address < stackLow || address > stackHigh - sizeof(value)) return false;
|
||||
std::memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value));
|
||||
return true;
|
||||
}
|
||||
@@ -104,6 +114,11 @@ struct Sampler {
|
||||
}
|
||||
|
||||
int walk(CONTEXT& context, std::array<std::uint64_t, WorkerDepth>& frames) {
|
||||
if (context.Rsp < stackLow || context.Rsp >= stackHigh) {
|
||||
stackLow = 0;
|
||||
stackHigh = 0;
|
||||
ReadableStackRegion(context.Rsp, stackLow, stackHigh);
|
||||
}
|
||||
const bool dwarf = stackHigh != 0 && context.Rsp >= stackLow && context.Rsp < stackHigh;
|
||||
int count = 0;
|
||||
while (count < depth && context.Rip != 0) {
|
||||
@@ -364,6 +379,7 @@ void StopWorkerSampler() {
|
||||
if (committerSamplerThread.joinable()) committerSamplerThread.join();
|
||||
}
|
||||
#else
|
||||
bool ReadableStackRegion(std::uint64_t, std::uint64_t&, std::uint64_t&) { return false; }
|
||||
void StartWorkerSampler(std::uint32_t) {}
|
||||
void StartCommitterSampler() {}
|
||||
void StopWorkerSampler() {}
|
||||
|
||||
@@ -127,26 +127,6 @@ int APS5_VABI sceAgcDriverTmpInitIdhs(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcDriverUserDataWritePacket(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcDriverUserDataWritePopMarker(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcDriverUserDataWritePushMarker(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcDriverUserDataWriteSetMarker(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
#include "prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp"
|
||||
#include "Recompiler.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -12,13 +15,30 @@ namespace AgcDriver::Graphics {
|
||||
|
||||
bool LoopGuardTripped();
|
||||
|
||||
struct BdaFaultChunk;
|
||||
|
||||
class BdaResources {
|
||||
public:
|
||||
explicit BdaResources(const Context& context);
|
||||
BdaResources(const Context& context, const GuestBufferMemory& memory);
|
||||
explicit BdaResources(const Context& context, bool reportOnly = false);
|
||||
BdaResources(const Context& context, const GuestBufferMemory& memory, bool reportOnly = false);
|
||||
~BdaResources();
|
||||
BdaResources(const BdaResources&) = delete;
|
||||
BdaResources& operator=(const BdaResources&) = delete;
|
||||
VkDescriptorBufferInfo Table() const;
|
||||
VkDescriptorBufferInfo Fault() const;
|
||||
void CheckFault() const;
|
||||
void NoteUse(std::uint64_t serial);
|
||||
bool TakeFaultSlot(const Context& context);
|
||||
bool HoldsFaultSlot() const { return faultChunk != nullptr; }
|
||||
static void NoteFinished(VkDevice device, std::uint64_t serial);
|
||||
struct FaultSlotCounts {
|
||||
std::uint64_t chunks = 0;
|
||||
std::uint64_t slots = 0;
|
||||
std::uint64_t held = 0;
|
||||
std::uint64_t reclaimed = 0;
|
||||
std::uint64_t retaken = 0;
|
||||
};
|
||||
static FaultSlotCounts FaultSlots(VkDevice device);
|
||||
struct ImageTableFaults {
|
||||
std::uint32_t stage = 0;
|
||||
std::uint64_t shader = 0;
|
||||
@@ -57,8 +77,13 @@ private:
|
||||
// BdaResources.cpp, which refers to it weakly).
|
||||
void markWrittenPages() const;
|
||||
void checkSrtGuard() const;
|
||||
std::span<std::byte> faultBytes() const;
|
||||
std::shared_ptr<Buffer> table;
|
||||
std::unique_ptr<Buffer> fault;
|
||||
VkDevice faultDevice = VK_NULL_HANDLE;
|
||||
std::shared_ptr<BdaFaultChunk> faultChunk;
|
||||
VkDeviceSize faultOffset = 0;
|
||||
bool reportOnly = false;
|
||||
std::uint64_t lastUse = 0;
|
||||
std::size_t tableBytes = 0;
|
||||
std::vector<ImageTableFaults> imageTables;
|
||||
std::vector<std::pair<std::uint64_t, std::uint64_t>> imageTableRanges;
|
||||
|
||||
@@ -28,6 +28,7 @@ struct BufferAllocation {
|
||||
bool slab = false;
|
||||
std::size_t bufferBytes = 0;
|
||||
std::uint32_t memoryType = 0;
|
||||
bool hostPlaced = false;
|
||||
};
|
||||
|
||||
struct SlabSlot {
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
VkDeviceMemory TakeImageMemory(const VkMemoryAllocateInfo& allocation, const char* operation, std::optional<std::uint32_t> hostType = std::nullopt, std::uint32_t* allocatedType = nullptr, bool newImage = false);
|
||||
void PutImageMemory(VkDeviceMemory memory, VkDeviceSize bytes, std::uint32_t memoryType) noexcept;
|
||||
std::size_t RetainedImages();
|
||||
std::optional<BufferAllocation> Take(std::size_t bytes, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, const char* category = nullptr);
|
||||
std::optional<BufferAllocation> Take(std::size_t bytes, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, const char* category = nullptr, bool hostPlaced = false);
|
||||
void Put(const BufferAllocation& allocation) noexcept;
|
||||
VkDeviceSize ReclaimIdleDevice(VkDeviceSize bytes, std::chrono::steady_clock::time_point now);
|
||||
static bool SlabEligible(std::size_t capacity, VkDeviceSize alignment, VkDeviceSize size, VkDeviceSize atom);
|
||||
@@ -106,11 +107,12 @@ private:
|
||||
VkBufferUsageFlags usage;
|
||||
VkMemoryPropertyFlags properties;
|
||||
std::uint32_t memoryType = 0;
|
||||
bool hostPlaced = false;
|
||||
bool operator==(const SlotKey&) const = default;
|
||||
};
|
||||
struct SlotKeyHash {
|
||||
std::size_t operator()(const SlotKey& key) const noexcept {
|
||||
return std::hash<std::size_t>{}(key.bytes) ^ (static_cast<std::size_t>(key.usage) << 32u) ^ (static_cast<std::size_t>(key.properties) << 48u) ^ (static_cast<std::size_t>(key.memoryType) << 56u);
|
||||
return std::hash<std::size_t>{}(key.bytes) ^ (static_cast<std::size_t>(key.usage) << 32u) ^ (static_cast<std::size_t>(key.properties) << 48u) ^ (static_cast<std::size_t>(key.memoryType) << 56u) ^ (static_cast<std::size_t>(key.hostPlaced) << 63u);
|
||||
}
|
||||
};
|
||||
// One retention tier: its slots by key (each list oldest first), their count and bytes, the
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#endif
|
||||
#include <mutex>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "prx/libc/include/PrimedSharedMutex.hpp"
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
@@ -35,6 +36,7 @@ class SamplerCache;
|
||||
class ShaderResources;
|
||||
class PlaceholderImages;
|
||||
class VertexInputCache;
|
||||
class VertexBufferFormats;
|
||||
|
||||
class PipelineCacheSynchronization {
|
||||
public:
|
||||
@@ -46,7 +48,7 @@ public:
|
||||
SnapshotLock TryLockForSnapshot() const { return SnapshotLock(mutex, std::try_to_lock); }
|
||||
|
||||
private:
|
||||
mutable std::shared_mutex mutex;
|
||||
mutable PrimedSharedMutex mutex;
|
||||
};
|
||||
|
||||
inline void Require(bool condition, const std::string& reason) {
|
||||
@@ -259,8 +261,11 @@ struct Context {
|
||||
bool earlyFragmentSampleMaskTestBeforeSampleCounting = false;
|
||||
bool primitiveListRestart = false;
|
||||
bool imageViewMinLod = false;
|
||||
bool shaderResourceMinLod = false;
|
||||
bool shaderImageMinLod = false;
|
||||
bool pipelineExecutableInfo = false;
|
||||
bool maintenance8 = false;
|
||||
bool pushDescriptors = false;
|
||||
bool graphicsPipelineLibrary = false;
|
||||
bool pipelineLinkTimeOptimization = true;
|
||||
std::uint32_t srgbDecodeFormats = 0;
|
||||
@@ -279,6 +284,7 @@ struct Context {
|
||||
return pipelineCacheSynchronization != nullptr ? pipelineCacheSynchronization->LockForPipelineUse() : PipelineCacheSynchronization::PipelineUseLock{};
|
||||
}
|
||||
VertexInputCache* vertexInputs = nullptr;
|
||||
VertexBufferFormats* vertexFormats = nullptr;
|
||||
|
||||
template<typename TFunction>
|
||||
TFunction Function(const char* name) const {
|
||||
@@ -330,35 +336,62 @@ struct Context {
|
||||
return type;
|
||||
}
|
||||
|
||||
std::uint32_t DeviceMemoryType(std::uint32_t mask, VkDeviceSize bytes, const char* what) const {
|
||||
const auto type = MemoryType(mask, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
if (memoryProperties2 == nullptr || physical == VK_NULL_HANDLE) return type;
|
||||
struct HeapReport {
|
||||
VkDeviceSize budget = 0;
|
||||
VkDeviceSize usage = 0;
|
||||
bool Fits(VkDeviceSize bytes) const { return budget == 0 || (usage < budget && bytes <= budget - usage); }
|
||||
};
|
||||
|
||||
HeapReport ReportedHeap(std::uint32_t heap) const {
|
||||
if (memoryProperties2 == nullptr || physical == VK_NULL_HANDLE) return {};
|
||||
VkPhysicalDeviceMemoryBudgetPropertiesEXT reported{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT};
|
||||
VkPhysicalDeviceMemoryProperties2 properties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
|
||||
properties.pNext = &reported;
|
||||
memoryProperties2(physical, &properties);
|
||||
return {reported.heapBudget[heap], reported.heapUsage[heap]};
|
||||
}
|
||||
|
||||
bool DeviceLocalFits(std::uint32_t mask, VkDeviceSize bytes) const {
|
||||
return ReportedHeap(memory.memoryTypes[MemoryType(mask, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)].heapIndex).Fits(bytes);
|
||||
}
|
||||
|
||||
std::uint32_t DeviceMemoryType(std::uint32_t mask, VkDeviceSize bytes, const char* what) const {
|
||||
const auto type = MemoryType(mask, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
const auto heap = memory.memoryTypes[type].heapIndex;
|
||||
const auto budget = reported.heapBudget[heap];
|
||||
const auto usage = reported.heapUsage[heap];
|
||||
if (budget == 0 || (usage < budget && bytes <= budget - usage)) return type;
|
||||
const auto report = ReportedHeap(heap);
|
||||
if (report.Fits(bytes)) return type;
|
||||
const auto host = HostMemoryType(mask);
|
||||
if (!host) return type;
|
||||
if (cacheReclaim != nullptr) {
|
||||
const auto wanted = bytes + (usage > budget ? usage - budget : 0u);
|
||||
const auto wanted = bytes + (report.usage > report.budget ? report.usage - report.budget : 0u);
|
||||
const auto released = cacheReclaim(wanted, true);
|
||||
if (released >= wanted) return type;
|
||||
if (released != 0) {
|
||||
memoryProperties2(physical, &properties);
|
||||
if (reported.heapUsage[heap] < reported.heapBudget[heap] && bytes <= reported.heapBudget[heap] - reported.heapUsage[heap]) return type;
|
||||
const auto after = ReportedHeap(heap);
|
||||
if (after.Fits(bytes)) return type;
|
||||
}
|
||||
}
|
||||
static std::atomic<std::uint64_t> placements{0}, placedBytes{0};
|
||||
const auto count = placements.fetch_add(1) + 1;
|
||||
const auto total = placedBytes.fetch_add(bytes) + bytes;
|
||||
if (count <= 5 || (count & (count - 1)) == 0) std::fprintf(stderr, "[gpu] %s: device-local heap %u uses %llu of its %llu MiB budget, %llu bytes placed in host memory type %u; %llu such allocations, %llu MiB\n", what, heap, static_cast<unsigned long long>(usage >> 20u), static_cast<unsigned long long>(budget >> 20u), static_cast<unsigned long long>(bytes), *host, static_cast<unsigned long long>(count), static_cast<unsigned long long>(total >> 20u));
|
||||
if (count <= 5 || (count & (count - 1)) == 0) std::fprintf(stderr, "[gpu] %s: device-local heap %u uses %llu of its %llu MiB budget, %llu bytes placed in host memory type %u; %llu such allocations, %llu MiB\n", what, heap, static_cast<unsigned long long>(report.usage >> 20u), static_cast<unsigned long long>(report.budget >> 20u), static_cast<unsigned long long>(bytes), *host, static_cast<unsigned long long>(count), static_cast<unsigned long long>(total >> 20u));
|
||||
return *host;
|
||||
}
|
||||
|
||||
bool DeviceLocalHeadroom(std::uint32_t type, VkDeviceSize bytes) const {
|
||||
if (memoryProperties2 == nullptr || physical == VK_NULL_HANDLE || type >= memory.memoryTypeCount) return true;
|
||||
const auto heap = memory.memoryTypes[type].heapIndex;
|
||||
if ((memory.memoryHeaps[heap].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) == 0) return true;
|
||||
VkPhysicalDeviceMemoryBudgetPropertiesEXT reported{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT};
|
||||
VkPhysicalDeviceMemoryProperties2 properties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, &reported};
|
||||
memoryProperties2(physical, &properties);
|
||||
const auto budget = reported.heapBudget[heap];
|
||||
if (budget == 0) return true;
|
||||
const auto limit = budget - budget / 8u;
|
||||
const auto usage = reported.heapUsage[heap];
|
||||
return usage < limit && bytes <= limit - usage;
|
||||
}
|
||||
|
||||
std::optional<std::uint32_t> HostMemoryType(std::uint32_t mask) const {
|
||||
for (std::uint32_t i = 0; i < memory.memoryTypeCount; ++i) {
|
||||
if ((mask & (1u << i)) != 0 && (memory.memoryHeaps[memory.memoryTypes[i].heapIndex].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) == 0) return i;
|
||||
|
||||
@@ -70,6 +70,8 @@ DccKeys TextureClearKeys(const GuestTextureResource& resource, std::uint64_t gue
|
||||
struct DccKeyProof {
|
||||
DccKeys keys = DccKeys::Uncompressed;
|
||||
std::uint64_t generation = 0;
|
||||
std::uint64_t pendingNote = 0;
|
||||
std::uint64_t pendingRecorder = 0;
|
||||
};
|
||||
// TextureClearKeys with the scan skipped while the key range is unchanged since `proof` was taken
|
||||
// (CollectWrites over the keys, then UnchangedSince its generation), so a surface's keys are scanned
|
||||
@@ -80,6 +82,8 @@ struct DccKeyProof {
|
||||
// their record), which makes the proof exactly as sound as UnchangedSince over the texels.
|
||||
// APS5_NO_KEY_FAST_PATH=1 scans on every call and stores nothing.
|
||||
DccKeys ProvedClearKeys(const GuestTextureResource& resource, std::uint64_t guestBytes, DccKeyProof& proof);
|
||||
DccKeyProof PendingKeyProof(const GuestTextureResource& resource, std::uint64_t guestBytes, DccKeys keys);
|
||||
bool PendingKeyProofHolds(const GuestTextureResource& resource, std::uint64_t guestBytes, const DccKeyProof& proof);
|
||||
bool KeyFastPath();
|
||||
bool SingleKeysReadable(const GuestTextureResource& resource);
|
||||
bool ReadSingleElement(const GuestTextureResource& resource, std::span<std::byte> element);
|
||||
|
||||
@@ -18,6 +18,7 @@ class Texture;
|
||||
class StorageTexture;
|
||||
|
||||
VkImageView DepthSurfaceView(const Context& context, const DepthTarget& target, bool depthWritten = true, bool stencilTested = false);
|
||||
VkImageView DepthSurfaceViewWithStencilWriteIntent(const Context& context, const DepthTarget& target, bool depthWritten, bool stencilTested, bool stencilWritten);
|
||||
SampleOrderTarget DepthSurfaceOrderTarget(const Context& context, const DepthTarget& target);
|
||||
DepthSampleLocations DepthSurfaceSampleLocations(const Context& context, const DepthTarget& target);
|
||||
enum class DepthPlaneScope { Overlapped, Whole };
|
||||
@@ -37,6 +38,8 @@ std::uint64_t DepthSliceBytes(VkExtent2D extent, std::uint32_t bytesPerTexel);
|
||||
bool DirectDepthCopy(const Context& context, VkFormat depthFormat, VkImageAspectFlagBits aspect, VkFormat colorFormat);
|
||||
void SetDirectDepthCopy(bool enabled);
|
||||
std::uint64_t DirectDepthCopyCount();
|
||||
void SetDepthTransferPasses(bool enabled);
|
||||
std::uint64_t DepthTransferPassCount();
|
||||
std::uint64_t MultisampledDepthBytes_nid_no_patch(VkExtent2D extent, std::uint32_t bytesPerTexel, std::uint32_t samples);
|
||||
void RequireNoResidentDepthRead_nid_no_patch(std::uint64_t address, std::size_t bytes, std::optional<std::pair<std::uint64_t, std::size_t>> htileClear = std::nullopt);
|
||||
void AppendHostWrittenDepthRanges(std::uint64_t address, std::size_t bytes, std::vector<std::pair<std::uint64_t, std::uint64_t>>& ranges);
|
||||
@@ -86,6 +89,7 @@ VkImageAspectFlags HtileFillClears(std::uint32_t pattern, bool stencilInHtile);
|
||||
std::uint64_t HtileMetadataBytes(VkExtent2D extent);
|
||||
bool HtileFillCovers(std::uint64_t htile, VkExtent2D extent, std::uint64_t address, std::size_t bytes);
|
||||
std::shared_ptr<Texture> DepthSurfaceTexture(const Context& context, std::span<const std::uint32_t> words, const GuestTextureResource& resource, VkComponentMapping components, VkImageViewType multisampleViewType = VK_IMAGE_VIEW_TYPE_2D);
|
||||
std::shared_ptr<Texture> DepthSurfaceFirstSample(const Context& context, std::span<const std::uint32_t> words, const GuestTextureResource& resource, VkComponentMapping components);
|
||||
std::size_t DepthPlaneCopyCount();
|
||||
VkDeviceSize DepthPlaneCopyBytes();
|
||||
VkFormat HostDepthFormat(const Context& context, VkFormat format);
|
||||
|
||||
@@ -57,6 +57,15 @@ inline VkDeviceSize HostImportOffset(const HostImport& import, std::uint64_t add
|
||||
return address - import.base + import.lead;
|
||||
}
|
||||
|
||||
struct HostImportStart {
|
||||
std::uint64_t guest;
|
||||
VkDeviceAddress device;
|
||||
};
|
||||
|
||||
inline HostImportStart HostImportBufferStart(const HostImport& import) {
|
||||
return {import.base - import.lead, import.address - import.lead};
|
||||
}
|
||||
|
||||
enum class ImportWatch : std::uint8_t { Watch, Unwatch };
|
||||
|
||||
struct ImportProbe {
|
||||
@@ -467,7 +476,9 @@ private:
|
||||
bool gpuCopy = false;
|
||||
VkBuffer copySource = VK_NULL_HANDLE;
|
||||
std::uint64_t copySourceBase = 0;
|
||||
VkDeviceAddress copySourceAddress = 0;
|
||||
bool copiedBack = false;
|
||||
std::shared_ptr<Buffer> shadowCopy;
|
||||
// An element the shader updates atomically lies inside (AddWritable's `atomic`).
|
||||
bool atomic = false;
|
||||
bool swept = false;
|
||||
|
||||
@@ -35,6 +35,8 @@ struct GuestSamplerResource {
|
||||
|
||||
GuestSamplerResource DecodeSamplerResource(std::span<const std::uint32_t> words, bool unnormalizedProven = false, bool forceDegammaPaired = false, bool integerBorder = false);
|
||||
std::optional<std::array<std::uint32_t, 4>> SingleLevelSamplerWords(std::span<const std::uint32_t, 4> words, bool singleLevelImage, bool mipmappedImage);
|
||||
bool HoldsLodAtZero(std::span<const std::uint32_t, 4> words);
|
||||
std::array<std::uint32_t, 4> PinnedLodSamplerWords(std::span<const std::uint32_t, 4> words, std::uint32_t lod);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Recompiler.hpp"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
|
||||
namespace AgcDriver::Graphics {
|
||||
@@ -141,6 +142,8 @@ constexpr TextureTileMode GcnMicroTileMode(TextureTileMode mode) {
|
||||
float EffectiveMinLod(const GuestTextureResource& resource);
|
||||
|
||||
bool IsNullTextureResource(std::span<const std::uint32_t> words);
|
||||
std::optional<std::uint64_t> TextureResourceAllocationAddress(std::span<const std::uint32_t> words);
|
||||
bool IsNullSampledTextureResource(std::span<const std::uint32_t> words);
|
||||
GuestTextureResource DecodeTextureResource(std::span<const std::uint32_t> words);
|
||||
std::array<std::uint32_t, 8> EncodeTextureResource(const GuestTextureResource& resource);
|
||||
bool DescriptorSingleLevel(std::span<const std::uint32_t> words);
|
||||
|
||||
@@ -157,7 +157,7 @@ bool ShadersWriteMemory(std::span<const CompiledShader> shaders);
|
||||
bool DeclaresEarlyFragmentTests(const ShaderRecompiler::RecompileResult& program);
|
||||
void ValidateSampleMask(const Context& context, const State& state, std::span<const CompiledShader> shaders);
|
||||
// Returns the color attachment locations the pixel shader writes.
|
||||
std::set<std::uint32_t> ValidateShaders(std::span<const CompiledShader> shaders, const State& state, const VkPhysicalDeviceSubgroupProperties& subgroup, bool fragmentShaderBarycentric, bool descriptorIndexing = false, bool imageInt64Atomics = false, bool geometryShader = false, bool sampleRateShading = false, bool bufferInt64Atomics = false, bool shaderClipDistance = false, bool shaderCullDistance = false, bool viewportIndexLayer = false, bool runtimeDescriptorArray = false, bool demoteToHelperInvocation = false, bool shaderTerminateInvocation = false, bool meshShader = true);
|
||||
std::set<std::uint32_t> ValidateShaders(std::span<const CompiledShader> shaders, const State& state, const VkPhysicalDeviceSubgroupProperties& subgroup, bool fragmentShaderBarycentric, bool descriptorIndexing = false, bool imageInt64Atomics = false, bool geometryShader = false, bool sampleRateShading = false, bool bufferInt64Atomics = false, bool shaderClipDistance = false, bool shaderCullDistance = false, bool viewportIndexLayer = false, bool runtimeDescriptorArray = false, bool demoteToHelperInvocation = false, bool shaderTerminateInvocation = false, bool meshShader = true, bool shaderResourceMinLod = false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -244,6 +244,7 @@ public:
|
||||
void CountSamples();
|
||||
bool CountingSamples() const { return countingSamples; }
|
||||
bool RecordMeshArguments(VkCommandBuffer commands, VkDeviceAddress record, VkDeviceAddress arguments, std::span<const std::uint32_t, 7> rules);
|
||||
bool RecordChangedCopy(VkCommandBuffer commands, VkDeviceAddress result, VkDeviceAddress snapshot, VkDeviceAddress target, std::uint32_t dwords, VkDeviceAddress counter = 0);
|
||||
std::uint64_t SamplesTotal();
|
||||
bool DumpSamples(VkDeviceAddress target, std::uint64_t address = 0);
|
||||
void NoteSampledDraw(VkCommandBuffer commands);
|
||||
@@ -394,6 +395,7 @@ public:
|
||||
// The function the flush hook calls, on the accessing thread (which may hold the GPU mutex),
|
||||
// when an access overlaps one of that thread's queued labels; it records them. Set once.
|
||||
static void SetQueuedLabelRecorder(void (*recorder)());
|
||||
static void FailNextSubmitsForTest(unsigned count);
|
||||
// Whether the lock-free pending-write snapshot (open, in-flight and finishing batches) overlaps
|
||||
// the range: false means no recorded work writes it, so a wait on it has nothing to submit.
|
||||
static bool SnapshotWriteOverlaps(std::uint64_t address, std::size_t bytes);
|
||||
@@ -769,6 +771,9 @@ private:
|
||||
int meshArgumentState = 0;
|
||||
VkPipelineLayout meshArgumentLayout = VK_NULL_HANDLE;
|
||||
VkPipeline meshArgumentPipeline = VK_NULL_HANDLE;
|
||||
int changedCopyState = 0;
|
||||
VkPipelineLayout changedCopyLayout = VK_NULL_HANDLE;
|
||||
VkPipeline changedCopyPipeline = VK_NULL_HANDLE;
|
||||
int sampleCounterState = 0;
|
||||
std::unique_ptr<Buffer> sampleCounter;
|
||||
VkPipelineLayout sampleLayout = VK_NULL_HANDLE;
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
~Buffer();
|
||||
Buffer(const Buffer&) = delete;
|
||||
Buffer& operator=(const Buffer&) = delete;
|
||||
static std::shared_ptr<Buffer> WithinDeviceLocalHeadroom(const Context& context, std::size_t size, VkBufferUsageFlags usage);
|
||||
VkBuffer Handle() const;
|
||||
VkDeviceAddress DeviceAddress() const;
|
||||
// Host-visible buffers only: a device-local one (properties without HOST_VISIBLE, the staging
|
||||
@@ -21,6 +22,7 @@ public:
|
||||
void Invalidate();
|
||||
|
||||
private:
|
||||
Buffer(const Context& context, std::size_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, bool headroom);
|
||||
void initializeAddress(VkBufferUsageFlags usage);
|
||||
void release() noexcept;
|
||||
Context context;
|
||||
|
||||
@@ -68,10 +68,10 @@ private:
|
||||
std::uint64_t misses = 0;
|
||||
};
|
||||
|
||||
void RequireFilterMinmax(const Context& context, VkFormat format, std::uint32_t samplerMask, std::span<const std::shared_ptr<Sampler>> samplers);
|
||||
bool ForcesDegammaOn(std::uint32_t guestFormat, std::uint32_t samplerMask, std::span<const std::shared_ptr<Sampler>> samplers);
|
||||
void RequireBorderSwizzle(std::uint32_t bcSwizzle, std::uint32_t samplerMask, std::span<const std::shared_ptr<Sampler>> samplers);
|
||||
void RequireNonSeamlessCube(bool cube, std::uint32_t samplerMask, std::span<const std::shared_ptr<Sampler>> samplers);
|
||||
void RequireFilterMinmax(const Context& context, VkFormat format, std::uint64_t samplerMask, std::span<const std::shared_ptr<Sampler>> samplers);
|
||||
bool ForcesDegammaOn(std::uint32_t guestFormat, std::uint64_t samplerMask, std::span<const std::shared_ptr<Sampler>> samplers);
|
||||
void RequireBorderSwizzle(std::uint32_t bcSwizzle, std::uint64_t samplerMask, std::span<const std::shared_ptr<Sampler>> samplers);
|
||||
void RequireNonSeamlessCube(bool cube, std::uint64_t samplerMask, std::span<const std::shared_ptr<Sampler>> samplers);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "prx/libSceAgcDriver/Graphics/include/Sampler.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Mutex.hpp"
|
||||
#include "Recompiler.hpp"
|
||||
#include "IntermediateRepresentation/IrMetadata/ResourcePlan.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/Shaders.hpp"
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
@@ -54,6 +55,7 @@ bool SampledTexturesShareEntry(std::span<const std::uint32_t> first, std::span<c
|
||||
bool AnyPendingCpuWrites(const Context& context);
|
||||
bool CompletePendingCpuWrites(const Context& context, std::uint64_t address, std::size_t bytes);
|
||||
bool SpirvStoresThroughAddresses(std::span<const std::uint32_t> words);
|
||||
bool SpirvFaultReportOnly(std::span<const std::uint32_t> words, std::uint32_t set, std::uint32_t binding);
|
||||
bool ShaderStoresThroughAddresses(const ShaderRecompiler::SharedSpirv& spirv);
|
||||
void LastRecordIndices(std::span<const void* const> logged, std::span<const void* const> objects, std::vector<std::size_t>& indices);
|
||||
|
||||
@@ -157,6 +159,7 @@ struct ImageTableReuseCounts {
|
||||
ImageTableReuseCounts ImageTableReuses();
|
||||
std::uint64_t SampledTexturesCleared();
|
||||
std::uint64_t SampledLookupKeyScans();
|
||||
std::uint64_t SampledLookupKeyProofs();
|
||||
|
||||
struct PresyncSurface {
|
||||
std::uint64_t address;
|
||||
@@ -504,6 +507,7 @@ private:
|
||||
bool depthCompare = false;
|
||||
VkImageViewType multisampleViewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
bool firstSample = false;
|
||||
bool layerRows = false;
|
||||
std::shared_ptr<Texture> texture;
|
||||
};
|
||||
PreviousSampled previousSampled;
|
||||
@@ -513,7 +517,7 @@ private:
|
||||
// lock and the cache still holds it; null sends the element to cachedTexture.
|
||||
std::shared_ptr<Texture> fastTexture(const ImageRecord& record);
|
||||
void resolveImageBinding(const ShaderRecompiler::DescriptorBinding& binding, Binding& item, std::span<const std::shared_ptr<Sampler>> shaderSamplers);
|
||||
void applyAnisoOverride();
|
||||
void applySamplerVariants();
|
||||
void forgetDeferredInputs();
|
||||
void release() noexcept;
|
||||
void prepareAddressBindings(std::span<const CompiledShader> shaders, std::span<const GuestMemorySnapshot> snapshots);
|
||||
@@ -586,6 +590,7 @@ private:
|
||||
std::vector<BdaResources::SrtGuardFaults> srtGuardFaults;
|
||||
bool usesBda = false;
|
||||
bool bdaReadOnly = true;
|
||||
bool faultReportOnly = true;
|
||||
std::vector<std::uint64_t> multisampleSources;
|
||||
bool usesFaultBuffer = false;
|
||||
bool faultChecks = false;
|
||||
@@ -618,9 +623,16 @@ private:
|
||||
std::shared_ptr<const TableDescriptors> keptTable(std::size_t set, std::shared_ptr<const std::vector<std::weak_ptr<Texture>>>& held) noexcept;
|
||||
std::uint32_t setOf(const Binding& binding) const;
|
||||
std::vector<Allocation> allocations;
|
||||
std::vector<VkDescriptorBufferInfo> descriptorBuffers;
|
||||
mutable std::vector<VkDescriptorBufferInfo> descriptorBuffers;
|
||||
std::vector<VkDescriptorImageInfo> descriptorImages;
|
||||
std::vector<VkWriteDescriptorSet> descriptorWrites;
|
||||
struct FaultDescriptor {
|
||||
std::size_t write;
|
||||
std::size_t buffer;
|
||||
std::uint32_t element;
|
||||
};
|
||||
std::vector<FaultDescriptor> faultDescriptors;
|
||||
void prepareFaultSlot() const;
|
||||
mutable std::vector<VkDescriptorPoolSize> drawPoolSizes;
|
||||
// Guest buffer elements bound read-only: each use of this object skips that many pending-write
|
||||
// notes (counted in MarkGpuWrites for the [buffers] line).
|
||||
@@ -651,11 +663,13 @@ private:
|
||||
bool integerBorder = false;
|
||||
bool singleLevelImage = false;
|
||||
bool mipmappedImage = false;
|
||||
std::optional<std::uint32_t> pinnedLod;
|
||||
};
|
||||
std::vector<SamplerSource> samplerSources;
|
||||
bool reusable = false;
|
||||
std::vector<DirectRegion> directRegions;
|
||||
std::vector<ValidatedSurface> validatedTextures;
|
||||
std::vector<ShaderRecompiler::RegisteredImageView> registeredImageViews;
|
||||
// The pending registry's serial at the last Revalidate that proved this object, taken before
|
||||
// its checks and kept only when unchanged after them (0: none): while it is still the serial,
|
||||
// no image other than the object's own sources has results pending over its surfaces and
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define CORE_LIBS_PRX_LIBSCEAGCDRIVER_GRAPHICS_INCLUDE_SHADERS_HPP
|
||||
|
||||
#include "prx/libSceAgcDriver/Graphics/include/Context.hpp"
|
||||
#include "IntermediateRepresentation/IrMetadata/ResourcePlan.hpp"
|
||||
#include "Recompiler.hpp"
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
@@ -37,6 +38,7 @@ struct CompiledShader {
|
||||
ShaderRecompiler::ShaderStage stage;
|
||||
const ShaderRecompiler::RecompileResult* program;
|
||||
std::uint32_t pushConstantOffset;
|
||||
const std::vector<ShaderRecompiler::RegisteredImageView>* registeredImageViews = nullptr;
|
||||
};
|
||||
|
||||
inline VkShaderStageFlagBits VulkanStage(ShaderRecompiler::ShaderStage stage) {
|
||||
|
||||
@@ -111,6 +111,7 @@ struct DepthTarget {
|
||||
bool htilePipeAligned = false;
|
||||
std::uint32_t htileVrsEncoding = 0;
|
||||
bool htileDepthOnly = false;
|
||||
bool gcn = false;
|
||||
};
|
||||
|
||||
struct State {
|
||||
|
||||
@@ -60,7 +60,7 @@ struct OwnedImage {
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
Texture(const Context& context, TextureDetiler& detiler, const GuestTextureResource& descriptor, VkComponentMapping components, std::span<const std::byte> snapshot, bool depthCompare = false, const VkClearColorValue* clear = nullptr);
|
||||
Texture(const Context& context, TextureDetiler& detiler, const GuestTextureResource& descriptor, VkComponentMapping components, std::span<const std::byte> snapshot, bool depthCompare = false, bool layerRows = false, const VkClearColorValue* clear = nullptr);
|
||||
Texture(const Context& context, const std::shared_ptr<ResidentColor>& source, const GuestTextureResource& descriptor, VkComponentMapping components);
|
||||
// A view of a storage image's own VkImage: the sampled texture follows the image's content, so a
|
||||
// compute pass writing it and the next pass sampling it share one image and copy nothing.
|
||||
@@ -303,9 +303,12 @@ public:
|
||||
static bool UnwatchHookLocksGpu(std::span<const std::pair<std::uint64_t, std::uint64_t>> ranges);
|
||||
static void SetPublishHookForTest(void (*hook)());
|
||||
static constexpr std::uint64_t SmallStoreBytes = 64 * 1024;
|
||||
static constexpr std::uint64_t OccasionalStoreBytes = 1024 * 1024;
|
||||
static constexpr std::uint64_t OccasionalWriteFlips = 8;
|
||||
static std::size_t StoreSmallPending(const char* reason);
|
||||
static void StoreReadbackBeforeLabel(const char* reason);
|
||||
static void StoreReadbackBeforeLabel(const char* reason, VkDevice device = VK_NULL_HANDLE);
|
||||
static std::size_t StoreDrawnLinear(const char* reason);
|
||||
static void NoteFlip();
|
||||
static std::size_t StoreDrawnLinearTouching(const char* reason, const std::function<bool(std::uint64_t, std::uint64_t)>& touches, bool all);
|
||||
static bool AnyPending();
|
||||
static void FlushDumpSelected(const char* reason);
|
||||
@@ -471,6 +474,7 @@ public:
|
||||
static std::uint64_t HandedOverSuperseded();
|
||||
static void SetClearHandOver(bool enabled);
|
||||
static std::uint64_t UntrackedCompares();
|
||||
static std::uint64_t OccasionalLabelStores();
|
||||
std::uint64_t GuestBytes() const;
|
||||
std::uint64_t BudgetBytes() const;
|
||||
std::size_t OriginalSnapshotBytes() const { return original.capacity(); }
|
||||
@@ -518,9 +522,11 @@ private:
|
||||
void releaseReadTraps(bool sharingPages);
|
||||
void storeTrappedOverlaps(const char* reason);
|
||||
bool unchangedSinceBaseline(std::uint64_t from, std::uint64_t to) const;
|
||||
bool cpuLeftUnchanged(std::uint32_t layer, std::uint64_t from, std::uint64_t to, bool edge) const;
|
||||
void saveBeforeUnwatch();
|
||||
void forgetKeptAtUnwatch(std::uint32_t unit);
|
||||
bool keptAtUnwatchHolds(std::uint64_t from, std::uint32_t unit) const;
|
||||
bool keptForCpu(std::uint32_t unit) const;
|
||||
// Drops the saved guest bytes of the units over [address, address + bytes) (another image's fill
|
||||
// or copy supersedes them there); the other units' bytes stay valid.
|
||||
void forgetSavedOver(std::uint64_t address, std::size_t bytes);
|
||||
@@ -747,6 +753,7 @@ private:
|
||||
std::uint32_t trackedLayers = 1;
|
||||
std::uint64_t trackedLayerBytes = 0;
|
||||
std::vector<std::uint64_t> layerGeneration;
|
||||
std::vector<std::uint64_t> layerPendingSince;
|
||||
std::vector<std::uint64_t> completionKept;
|
||||
UnitFlags layerPending;
|
||||
std::vector<bool> layerBehind;
|
||||
@@ -795,6 +802,8 @@ private:
|
||||
bool pendingFromOthers = false;
|
||||
std::vector<DrawnRect> drawnRects;
|
||||
std::vector<std::uint64_t> storeNotes;
|
||||
std::uint64_t writtenFlip = 0;
|
||||
std::atomic<bool> writtenOccasionally{false};
|
||||
std::uint64_t version = 0;
|
||||
std::uint64_t writes = 0;
|
||||
// `original` holds the guest bytes; false after a GPU-side clear, which never read them.
|
||||
|
||||
@@ -92,6 +92,8 @@ namespace AgcDriver::Graphics {
|
||||
VkShaderModule imageModule = VK_NULL_HANDLE;
|
||||
VkShaderModule repackModule = VK_NULL_HANDLE;
|
||||
VkPipeline repackPipeline = VK_NULL_HANDLE;
|
||||
VkShaderModule imageWordModule = VK_NULL_HANDLE;
|
||||
VkShaderModule wordModule = VK_NULL_HANDLE;
|
||||
DescriptorRing imageDescriptorSets;
|
||||
VkDescriptorSetLayout readbackDescriptorLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout readbackPipelineLayout = VK_NULL_HANDLE;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -128,14 +127,39 @@ inline std::array<char, 160> VertexDescriptorFlagsMessage(const ShaderRecompiler
|
||||
return message;
|
||||
}
|
||||
|
||||
inline bool QueryVertexBufferFormat(const Context& context, VkFormat format) {
|
||||
VkFormatProperties properties{};
|
||||
context.formatProperties(context.physical, format, &properties);
|
||||
return (properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0;
|
||||
}
|
||||
|
||||
class VertexBufferFormats {
|
||||
public:
|
||||
bool Supported(const Context& context, VkFormat format) {
|
||||
const auto index = static_cast<std::size_t>(format);
|
||||
if (index >= known.size()) return QueryVertexBufferFormat(context, format);
|
||||
auto state = known[index].load(std::memory_order_relaxed);
|
||||
if (state == 0) {
|
||||
state = QueryVertexBufferFormat(context, format) ? 2 : 1;
|
||||
known[index].store(state, std::memory_order_relaxed);
|
||||
}
|
||||
return state == 2;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<std::atomic<std::uint8_t>, VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1> known{};
|
||||
};
|
||||
|
||||
inline VertexInputLayout BuildVertexInputLayout(const Context& context, std::span<const ShaderRecompiler::VertexAttribute> attributes) {
|
||||
Require(attributes.size() <= context.limits.maxVertexInputBindings && attributes.size() <= context.limits.maxVertexInputAttributes, "vertex input count exceeds device limits");
|
||||
VertexInputLayout result;
|
||||
std::set<std::uint32_t> locations;
|
||||
result.bindings.reserve(attributes.size());
|
||||
result.attributes.reserve(attributes.size());
|
||||
for (const auto& attribute : attributes) {
|
||||
const auto& fields = attribute.resource.fields;
|
||||
const auto format = DecodeVertexFormat(attribute);
|
||||
Require(attribute.location < context.limits.maxVertexInputAttributes && locations.insert(attribute.location).second, "invalid or duplicate vertex attribute location");
|
||||
const auto duplicate = std::any_of(result.attributes.begin(), result.attributes.end(), [&](const auto& described) { return described.location == attribute.location; });
|
||||
Require(attribute.location < context.limits.maxVertexInputAttributes && !duplicate, "invalid or duplicate vertex attribute location");
|
||||
Require(attribute.fetchIndex <= 1, "unsupported vertex fetch index");
|
||||
if ((fields[1] & 0x80000000u) != 0 || (fields[3] & 0x00800000u) != 0 || (fields[3] >> 30u) != 0) {
|
||||
Require(false, VertexDescriptorFlagsMessage(attribute).data());
|
||||
@@ -146,9 +170,7 @@ inline VertexInputLayout BuildVertexInputLayout(const Context& context, std::spa
|
||||
Require(stride <= context.limits.maxVertexInputBindingStride, "vertex stride exceeds device limits");
|
||||
Require(context.formatProperties != nullptr, "missing vertex format property query");
|
||||
const auto supported = [&](VkFormat candidate) {
|
||||
VkFormatProperties properties{};
|
||||
context.formatProperties(context.physical, candidate, &properties);
|
||||
return (properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0;
|
||||
return context.vertexFormats != nullptr ? context.vertexFormats->Supported(context, candidate) : QueryVertexBufferFormat(context, candidate);
|
||||
};
|
||||
auto host = format.format;
|
||||
auto hostSupported = supported(host);
|
||||
@@ -156,7 +178,7 @@ inline VertexInputLayout BuildVertexInputLayout(const Context& context, std::spa
|
||||
host = DecodeVertexFormat(attribute, components).format;
|
||||
hostSupported = supported(host);
|
||||
}
|
||||
Require(hostSupported, "device does not support vertex format " + std::to_string(format.format));
|
||||
if (!hostSupported) Require(false, "device does not support vertex format " + std::to_string(format.format));
|
||||
const auto binding = static_cast<std::uint32_t>(result.bindings.size());
|
||||
result.bindings.push_back({binding, stride, attribute.fetchIndex == 0 ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE});
|
||||
result.attributes.push_back({attribute.location, binding, host, 0});
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#version 450
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8) in;
|
||||
layout(set = 0, binding = 0) uniform texture2D depthPlane;
|
||||
layout(set = 0, binding = 1, r32ui) uniform writeonly uimage2D texels;
|
||||
layout(push_constant) uniform Push {
|
||||
uvec2 offset;
|
||||
uvec2 extent;
|
||||
} push;
|
||||
|
||||
void main() {
|
||||
if (any(greaterThanEqual(gl_GlobalInvocationID.xy, push.extent))) return;
|
||||
const ivec2 position = ivec2(push.offset + gl_GlobalInvocationID.xy);
|
||||
imageStore(texels, position, uvec4(floatBitsToUint(texelFetch(depthPlane, position, 0).r)));
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#version 450
|
||||
#extension GL_EXT_buffer_reference : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
layout(local_size_x = 64) in;
|
||||
layout(buffer_reference, std430, buffer_reference_align = 4) buffer Words { uint words[]; };
|
||||
layout(push_constant) uniform Parameters {
|
||||
Words result;
|
||||
Words snapshot;
|
||||
Words target;
|
||||
Words counter;
|
||||
uint count;
|
||||
uint always;
|
||||
} parameters;
|
||||
|
||||
uint differingBytes(uint difference) {
|
||||
uint folded = difference | (difference >> 1u);
|
||||
folded |= folded >> 2u;
|
||||
folded |= folded >> 4u;
|
||||
return (folded & 0x01010101u) * 0xffu;
|
||||
}
|
||||
|
||||
void main() {
|
||||
uint index = gl_GlobalInvocationID.x;
|
||||
if (index >= parameters.count) return;
|
||||
uint value = parameters.result.words[index];
|
||||
uint before = parameters.snapshot.words[index];
|
||||
uint held = parameters.target.words[index];
|
||||
uint changed = differingBytes(value ^ before);
|
||||
uint kept = differingBytes(held ^ before);
|
||||
uint stored = parameters.always != 0u ? 0xffffffffu : changed & ~kept;
|
||||
if (stored != 0u) parameters.target.words[index] = (held & ~stored) | (value & stored);
|
||||
if (uint64_t(parameters.counter) != 0ul && (changed & kept) != 0u) atomicAdd(parameters.counter.words[0], 1u);
|
||||
}
|
||||
@@ -207,34 +207,27 @@ void copyElement(uint src, uint dst) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
uvec2 p = gl_GlobalInvocationID.xy + uvec2(params.columnBegin, params.rowBegin);
|
||||
if (p.x >= params.width || p.y >= params.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool locate(uvec2 p, out uint src, out uint dst, out uint ranged) {
|
||||
uint linearOffset = p.y * params.pitchBytes + p.x * ELEMENT_BYTES;
|
||||
|
||||
if (TILE_FAMILY == 0u) {
|
||||
// kLinear: guest and host layouts match; a straight copy at the
|
||||
// same pitch, no swizzle.
|
||||
ranged = linearOffset;
|
||||
if (linearOffset < params.rangeBegin || linearOffset >= params.rangeEnd) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
#ifdef LINEAR_IMAGE
|
||||
if (RETILE != 0u) {
|
||||
loadElement(p, params.dstBase + linearOffset - params.tiledBase);
|
||||
} else {
|
||||
storeElement(params.srcBase + linearOffset - params.tiledBase, p);
|
||||
}
|
||||
src = params.srcBase + linearOffset - params.tiledBase;
|
||||
dst = params.dstBase + linearOffset - params.tiledBase;
|
||||
#else
|
||||
if (RETILE != 0u) {
|
||||
copyElement(params.srcBase + linearOffset - params.linearBase, params.dstBase + linearOffset - params.tiledBase);
|
||||
src = params.srcBase + linearOffset - params.linearBase;
|
||||
dst = params.dstBase + linearOffset - params.tiledBase;
|
||||
} else {
|
||||
copyElement(params.srcBase + linearOffset - params.tiledBase, params.dstBase + linearOffset - params.linearBase);
|
||||
src = params.srcBase + linearOffset - params.tiledBase;
|
||||
dst = params.dstBase + linearOffset - params.linearBase;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
uvec2 swizzle = p;
|
||||
@@ -251,24 +244,106 @@ void main() {
|
||||
uint split = equationBit(SPLIT0, p) | (equationBit(SPLIT1, p) << 1) | (equationBit(SPLIT2, p) << 2) | (equationBit(SPLIT3, p) << 3);
|
||||
tiledOffset += split * params.splitStride;
|
||||
}
|
||||
ranged = tiledOffset;
|
||||
if (tiledOffset < params.rangeBegin || tiledOffset >= params.rangeEnd) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
tiledOffset -= params.tiledBase;
|
||||
linearOffset -= params.linearBase;
|
||||
|
||||
#ifdef LINEAR_IMAGE
|
||||
if (RETILE != 0u) {
|
||||
loadElement(p, params.dstBase + tiledOffset);
|
||||
} else {
|
||||
storeElement(params.srcBase + tiledOffset, p);
|
||||
}
|
||||
src = params.srcBase + tiledOffset;
|
||||
dst = params.dstBase + tiledOffset;
|
||||
#else
|
||||
if (RETILE != 0u) {
|
||||
copyElement(params.srcBase + linearOffset, params.dstBase + tiledOffset);
|
||||
src = params.srcBase + linearOffset;
|
||||
dst = params.dstBase + tiledOffset;
|
||||
} else {
|
||||
copyElement(params.srcBase + tiledOffset, params.dstBase + linearOffset);
|
||||
src = params.srcBase + tiledOffset;
|
||||
dst = params.dstBase + linearOffset;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void moveElement(uvec2 p) {
|
||||
uint src;
|
||||
uint dst;
|
||||
uint ranged;
|
||||
if (!locate(p, src, dst, ranged)) {
|
||||
return;
|
||||
}
|
||||
#ifdef LINEAR_IMAGE
|
||||
if (RETILE != 0u) {
|
||||
loadElement(p, dst);
|
||||
} else {
|
||||
storeElement(src, p);
|
||||
}
|
||||
#else
|
||||
copyElement(src, dst);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WORD_GROUPS
|
||||
shared uint groupWords[32];
|
||||
shared uint groupLanes[32];
|
||||
shared uint groupDestinations[64];
|
||||
|
||||
void main() {
|
||||
uvec2 p = gl_GlobalInvocationID.xy + uvec2(params.columnBegin, params.rowBegin);
|
||||
bool inside = p.x < params.width && p.y < params.height;
|
||||
uint lane = gl_LocalInvocationID.y * gl_WorkGroupSize.x + gl_LocalInvocationID.x;
|
||||
uint count = 4u / ELEMENT_BYTES;
|
||||
uint slot = lane / count;
|
||||
uint index = lane % count;
|
||||
uint src = 0u;
|
||||
uint dst = 0u;
|
||||
uint ranged = 0u;
|
||||
bool valid = inside && locate(p, src, dst, ranged);
|
||||
if (index == 0u) {
|
||||
groupWords[slot] = 0u;
|
||||
groupLanes[slot] = 0u;
|
||||
}
|
||||
groupDestinations[lane] = dst;
|
||||
barrier();
|
||||
if (valid) {
|
||||
uint mask = ELEMENT_BYTES == 1u ? 0xffu : 0xffffu;
|
||||
#ifdef LINEAR_IMAGE
|
||||
uint value = imageLoad(linearImage, ivec2(p)).x & mask;
|
||||
#else
|
||||
uint value = (inputBuffer.data[src >> 2] >> ((src & 3u) * 8u)) & mask;
|
||||
#endif
|
||||
atomicOr(groupWords[slot], value << (index * ELEMENT_BYTES * 8u));
|
||||
atomicOr(groupLanes[slot], 1u << index);
|
||||
}
|
||||
barrier();
|
||||
uint first = groupDestinations[slot * count];
|
||||
bool whole = groupLanes[slot] == (1u << count) - 1u && (first & 3u) == 0u;
|
||||
for (uint i = 1u; i < count; ++i) {
|
||||
whole = whole && groupDestinations[slot * count + i] == first + i * ELEMENT_BYTES;
|
||||
}
|
||||
if (whole) {
|
||||
if (index == 0u) {
|
||||
#ifdef LINEAR_IMAGE
|
||||
tiledBuffer.data[first >> 2] = groupWords[slot];
|
||||
#else
|
||||
outputBuffer.data[first >> 2] = groupWords[slot];
|
||||
#endif
|
||||
}
|
||||
} else if (valid) {
|
||||
#ifdef LINEAR_IMAGE
|
||||
loadElement(p, dst);
|
||||
#else
|
||||
copyElement(src, dst);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
void main() {
|
||||
uvec2 p = gl_GlobalInvocationID.xy + uvec2(params.columnBegin, params.rowBegin);
|
||||
if (p.x >= params.width || p.y >= params.height) {
|
||||
return;
|
||||
}
|
||||
moveElement(p);
|
||||
}
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "ImageTableAbi.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <cstdio>
|
||||
@@ -13,7 +14,12 @@
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <iomanip>
|
||||
#include <span>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace AgcDriver::Graphics {
|
||||
|
||||
@@ -104,15 +110,207 @@ std::uint64_t hashRanges(const std::vector<ShaderRecompiler::BdaAbi::Range>& ran
|
||||
|
||||
}
|
||||
|
||||
BdaResources::BdaResources(const Context& context) {
|
||||
static_assert(std::endian::native == std::endian::little);
|
||||
Require(ShaderRecompiler::BdaAbi::FaultBufferBytes <= context.limits.maxStorageBufferRange, "BDA fault buffer exceeds storage buffer range limit");
|
||||
fault = std::make_unique<Buffer>(context, ShaderRecompiler::BdaAbi::FaultBufferBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
std::memset(fault->Bytes().data(), 0, ShaderRecompiler::BdaAbi::WrittenListWord * sizeof(std::uint32_t));
|
||||
std::memset(fault->Bytes().data() + ShaderRecompiler::BdaAbi::SrtGuardWord * sizeof(std::uint32_t), 0, sizeof(std::uint32_t));
|
||||
struct BdaFaultChunk {
|
||||
std::unique_ptr<Buffer> buffer;
|
||||
std::vector<VkDeviceSize> free;
|
||||
std::size_t slots = 0;
|
||||
VkDeviceSize slotBytes = 0;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
struct FaultArena {
|
||||
std::vector<std::shared_ptr<BdaFaultChunk>> chunks;
|
||||
std::unordered_set<BdaResources*> holders;
|
||||
std::uint64_t finished = 0;
|
||||
BdaResources::FaultSlotCounts counts;
|
||||
};
|
||||
|
||||
struct FaultArenas {
|
||||
std::mutex mutex;
|
||||
std::unordered_map<VkDevice, FaultArena> devices;
|
||||
};
|
||||
|
||||
FaultArenas& faultArenas() {
|
||||
static auto* arenas = new FaultArenas();
|
||||
return *arenas;
|
||||
}
|
||||
|
||||
BdaResources::BdaResources(const Context& context, const GuestBufferMemory& memory) : BdaResources(context) {
|
||||
bool sharedFaultSlots() {
|
||||
static const bool shared = std::getenv("APS5_NO_SHARED_FAULT_SLOTS") == nullptr;
|
||||
return shared;
|
||||
}
|
||||
|
||||
constexpr VkDeviceSize FaultChunkBytes = VkDeviceSize{512} * 1024;
|
||||
|
||||
VkDeviceSize faultSlotBytes(bool reportOnly) {
|
||||
return reportOnly ? sizeof(ShaderRecompiler::BdaAbi::Fault) : ShaderRecompiler::BdaAbi::FaultBufferBytes;
|
||||
}
|
||||
|
||||
VkDeviceSize faultStride(const Context& context, VkDeviceSize bytes) {
|
||||
const auto alignment = std::max<VkDeviceSize>(context.limits.minStorageBufferOffsetAlignment, sizeof(std::uint32_t));
|
||||
return (bytes + alignment - 1) / alignment * alignment;
|
||||
}
|
||||
|
||||
bool faultSlotClean(std::span<const std::byte> bytes) {
|
||||
namespace Abi = ShaderRecompiler::BdaAbi;
|
||||
if (bytes.size() < Abi::FaultBufferBytes) return std::all_of(bytes.begin(), bytes.end(), [](std::byte value) { return value == std::byte{0}; });
|
||||
std::array<std::uint32_t, Abi::WrittenSlotsWord> head{};
|
||||
std::memcpy(head.data(), bytes.data(), sizeof(head));
|
||||
std::uint32_t guard = 0;
|
||||
std::memcpy(&guard, bytes.data() + Abi::SrtGuardWord * sizeof(std::uint32_t), sizeof(guard));
|
||||
return guard == 0 && std::all_of(head.begin(), head.end(), [](std::uint32_t word) { return word == 0; });
|
||||
}
|
||||
|
||||
void clearFaultSlot(std::span<std::byte> bytes) {
|
||||
namespace Abi = ShaderRecompiler::BdaAbi;
|
||||
if (bytes.size() < Abi::FaultBufferBytes) {
|
||||
std::memset(bytes.data(), 0, bytes.size());
|
||||
return;
|
||||
}
|
||||
std::memset(bytes.data(), 0, Abi::WrittenListWord * sizeof(std::uint32_t));
|
||||
std::memset(bytes.data() + Abi::SrtGuardWord * sizeof(std::uint32_t), 0, sizeof(std::uint32_t));
|
||||
}
|
||||
|
||||
void dropChunk(FaultArena& arena, const std::shared_ptr<BdaFaultChunk>& chunk, std::vector<std::shared_ptr<BdaFaultChunk>>& dropped) {
|
||||
const auto found = std::find(arena.chunks.begin(), arena.chunks.end(), chunk);
|
||||
if (found == arena.chunks.end()) return;
|
||||
arena.counts.slots -= (*found)->slots;
|
||||
--arena.counts.chunks;
|
||||
dropped.push_back(std::move(*found));
|
||||
arena.chunks.erase(found);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BdaResources::BdaResources(const Context& context, bool reportOnly) : reportOnly(reportOnly) {
|
||||
static_assert(std::endian::native == std::endian::little);
|
||||
Require(ShaderRecompiler::BdaAbi::FaultBufferBytes <= context.limits.maxStorageBufferRange, "BDA fault buffer exceeds storage buffer range limit");
|
||||
TakeFaultSlot(context);
|
||||
}
|
||||
|
||||
BdaResources::~BdaResources() {
|
||||
std::vector<std::shared_ptr<BdaFaultChunk>> dropped;
|
||||
auto& arenas = faultArenas();
|
||||
std::lock_guard lock(arenas.mutex);
|
||||
if (faultChunk == nullptr) return;
|
||||
const auto bytes = faultBytes();
|
||||
if (!faultSlotClean(bytes)) clearFaultSlot(bytes);
|
||||
const auto chunk = faultChunk;
|
||||
dropped.push_back(std::move(faultChunk));
|
||||
const auto found = arenas.devices.find(faultDevice);
|
||||
if (found == arenas.devices.end()) return;
|
||||
auto& arena = found->second;
|
||||
arena.holders.erase(this);
|
||||
--arena.counts.held;
|
||||
if (!sharedFaultSlots()) {
|
||||
arena.counts.slots -= chunk->slots;
|
||||
--arena.counts.chunks;
|
||||
} else {
|
||||
chunk->free.push_back(faultOffset);
|
||||
if (chunk->free.size() == chunk->slots) dropChunk(arena, chunk, dropped);
|
||||
}
|
||||
if (arena.holders.empty()) {
|
||||
while (!arena.chunks.empty()) dropChunk(arena, arena.chunks.back(), dropped);
|
||||
arenas.devices.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
std::span<std::byte> BdaResources::faultBytes() const {
|
||||
return faultChunk->buffer->Bytes().subspan(static_cast<std::size_t>(faultOffset), static_cast<std::size_t>(faultChunk->slotBytes));
|
||||
}
|
||||
|
||||
void BdaResources::NoteUse(std::uint64_t serial) {
|
||||
auto& arenas = faultArenas();
|
||||
std::lock_guard lock(arenas.mutex);
|
||||
lastUse = std::max(lastUse, serial);
|
||||
}
|
||||
|
||||
void BdaResources::NoteFinished(VkDevice device, std::uint64_t serial) {
|
||||
auto& arenas = faultArenas();
|
||||
std::lock_guard lock(arenas.mutex);
|
||||
const auto found = arenas.devices.find(device);
|
||||
if (found != arenas.devices.end()) found->second.finished = serial;
|
||||
}
|
||||
|
||||
BdaResources::FaultSlotCounts BdaResources::FaultSlots(VkDevice device) {
|
||||
auto& arenas = faultArenas();
|
||||
std::lock_guard lock(arenas.mutex);
|
||||
const auto found = arenas.devices.find(device);
|
||||
return found != arenas.devices.end() ? found->second.counts : FaultSlotCounts{};
|
||||
}
|
||||
|
||||
bool BdaResources::TakeFaultSlot(const Context& context) {
|
||||
if (faultChunk != nullptr) return false;
|
||||
std::vector<std::shared_ptr<BdaFaultChunk>> dropped;
|
||||
auto& arenas = faultArenas();
|
||||
std::lock_guard lock(arenas.mutex);
|
||||
auto& arena = arenas.devices[context.device];
|
||||
const bool retake = faultDevice != VK_NULL_HANDLE;
|
||||
if (!retake) lastUse = arena.finished + 1;
|
||||
faultDevice = context.device;
|
||||
const bool shared = sharedFaultSlots();
|
||||
const auto slotBytes = shared ? faultSlotBytes(reportOnly) : VkDeviceSize{ShaderRecompiler::BdaAbi::FaultBufferBytes};
|
||||
const auto withFree = [&] { return std::find_if(arena.chunks.rbegin(), arena.chunks.rend(), [&](const std::shared_ptr<BdaFaultChunk>& chunk) { return chunk->slotBytes == slotBytes && !chunk->free.empty(); }); };
|
||||
auto source = shared ? withFree() : arena.chunks.rend();
|
||||
bool reclaimed = false;
|
||||
if (shared && source == arena.chunks.rend() && GuestMemory::GpuMutex().HeldByThisThread()) {
|
||||
std::vector<BdaResources*> idle;
|
||||
for (auto* holder : arena.holders) {
|
||||
if (holder->faultChunk->slotBytes == slotBytes && holder->lastUse <= arena.finished && faultSlotClean(holder->faultBytes())) idle.push_back(holder);
|
||||
}
|
||||
if (!idle.empty()) {
|
||||
const auto reclaim = (idle.size() + 1) / 2;
|
||||
std::nth_element(idle.begin(), idle.begin() + static_cast<std::ptrdiff_t>(reclaim - 1), idle.end(), [](const BdaResources* left, const BdaResources* right) { return left->lastUse < right->lastUse; });
|
||||
for (std::size_t index = 0; index < reclaim; ++index) {
|
||||
auto& holder = *idle[index];
|
||||
holder.faultChunk->free.push_back(holder.faultOffset);
|
||||
holder.faultChunk.reset();
|
||||
arena.holders.erase(&holder);
|
||||
--arena.counts.held;
|
||||
++arena.counts.reclaimed;
|
||||
}
|
||||
reclaimed = true;
|
||||
source = withFree();
|
||||
}
|
||||
}
|
||||
std::shared_ptr<BdaFaultChunk> chunk;
|
||||
if (source != arena.chunks.rend()) {
|
||||
chunk = *source;
|
||||
} else {
|
||||
const auto stride = shared ? faultStride(context, slotBytes) : slotBytes;
|
||||
const auto slots = shared ? std::max<VkDeviceSize>(1, FaultChunkBytes / stride) : 1;
|
||||
chunk = std::make_shared<BdaFaultChunk>();
|
||||
chunk->buffer = std::make_unique<Buffer>(context, static_cast<std::size_t>(stride * slots), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
std::memset(chunk->buffer->Bytes().data(), 0, chunk->buffer->Bytes().size());
|
||||
chunk->slots = static_cast<std::size_t>(slots);
|
||||
chunk->slotBytes = slotBytes;
|
||||
for (auto slot = slots; slot-- > 0;) chunk->free.push_back(slot * stride);
|
||||
if (shared) arena.chunks.push_back(chunk);
|
||||
arena.counts.slots += chunk->slots;
|
||||
++arena.counts.chunks;
|
||||
}
|
||||
faultOffset = chunk->free.back();
|
||||
chunk->free.pop_back();
|
||||
faultChunk = chunk;
|
||||
arena.holders.insert(this);
|
||||
++arena.counts.held;
|
||||
if (retake) ++arena.counts.retaken;
|
||||
bool spare = false;
|
||||
for (auto it = arena.chunks.begin(); reclaimed && it != arena.chunks.end();) {
|
||||
if ((*it)->free.size() != (*it)->slots || !std::exchange(spare, true)) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
arena.counts.slots -= (*it)->slots;
|
||||
--arena.counts.chunks;
|
||||
dropped.push_back(std::move(*it));
|
||||
it = arena.chunks.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BdaResources::BdaResources(const Context& context, const GuestBufferMemory& memory, bool reportOnly) : BdaResources(context, reportOnly) {
|
||||
const auto cached = memory.CachedAddressTable();
|
||||
std::vector<ShaderRecompiler::BdaAbi::Range> built;
|
||||
if (!cached.has_value()) built = memory.AddressRanges();
|
||||
@@ -228,7 +426,7 @@ VkDescriptorBufferInfo BdaResources::Table() const {
|
||||
}
|
||||
|
||||
VkDescriptorBufferInfo BdaResources::Fault() const {
|
||||
return {fault->Handle(), 0, ShaderRecompiler::BdaAbi::FaultBufferBytes};
|
||||
return {faultChunk->buffer->Handle(), faultOffset, faultChunk->slotBytes};
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -240,12 +438,13 @@ bool LoopGuardTripped() {
|
||||
}
|
||||
|
||||
void BdaResources::CheckFault() const {
|
||||
markWrittenPages();
|
||||
if (faultChunk == nullptr) return;
|
||||
if (!reportOnly) markWrittenPages();
|
||||
ShaderRecompiler::BdaAbi::Fault report{};
|
||||
std::memcpy(&report, fault->Bytes().data(), sizeof(report));
|
||||
std::memcpy(&report, faultBytes().data(), sizeof(report));
|
||||
if (report.state == ShaderRecompiler::BdaAbi::FaultState::Empty) {
|
||||
Require(static_cast<std::uint32_t>(report.reason) == 0 && report.address == 0 && report.bytes == 0 && report.stage == 0 && report.instruction == 0 && report.otherFaults == 0, "BDA fault record has data without publication");
|
||||
checkSrtGuard();
|
||||
if (!reportOnly) checkSrtGuard();
|
||||
return;
|
||||
}
|
||||
Require(report.state == ShaderRecompiler::BdaAbi::FaultState::Ready && report.otherFaults <= 1, "incomplete or invalid BDA fault record");
|
||||
@@ -254,7 +453,7 @@ void BdaResources::CheckFault() const {
|
||||
// APS5_LOOP_GUARD: the shader left a loop that ran past the guard; the dispatch result is kept.
|
||||
loopGuardTripped.store(true, std::memory_order_relaxed);
|
||||
std::fprintf(stderr, "[gpu] loop guard: the loop exit at pc 0x%x of shader 0x%llx ran past %u evaluations\n", report.instruction, static_cast<unsigned long long>(report.address), report.bytes);
|
||||
std::memset(fault->Bytes().data(), 0, fault->Bytes().size());
|
||||
std::memset(faultBytes().data(), 0, faultBytes().size());
|
||||
return;
|
||||
}
|
||||
if (report.reason == ShaderRecompiler::BdaAbi::FaultReason::ImageTable) {
|
||||
@@ -321,7 +520,7 @@ void BdaResources::SetSrtGuards(std::vector<SrtGuardFaults> guards) {
|
||||
void BdaResources::checkSrtGuard() const {
|
||||
namespace Abi = ShaderRecompiler::BdaAbi;
|
||||
std::uint32_t guard = 0;
|
||||
std::memcpy(&guard, fault->Bytes().data() + Abi::SrtGuardWord * sizeof(std::uint32_t), sizeof(guard));
|
||||
std::memcpy(&guard, faultBytes().data() + Abi::SrtGuardWord * sizeof(std::uint32_t), sizeof(guard));
|
||||
if (guard == 0) return;
|
||||
const auto stage = guard >> Abi::SrtGuardStageShift;
|
||||
const auto record = guard & ((1u << Abi::SrtGuardStageShift) - 1u);
|
||||
@@ -337,7 +536,7 @@ void BdaResources::checkSrtGuard() const {
|
||||
|
||||
void BdaResources::markWrittenPages() const {
|
||||
namespace Abi = ShaderRecompiler::BdaAbi;
|
||||
auto* words = reinterpret_cast<std::uint32_t*>(fault->Bytes().data());
|
||||
auto* words = reinterpret_cast<std::uint32_t*>(faultBytes().data());
|
||||
Require(words[Abi::WrittenOverflowWord] == 0, "more than " + std::to_string(Abi::WrittenPageSlots) + " chunks of " + std::to_string(Abi::WrittenChunkPages) + " pages stored to through the BDA table in one use are not implemented");
|
||||
const auto count = words[Abi::WrittenCountWord];
|
||||
if (count == 0) return;
|
||||
|
||||
@@ -399,7 +399,7 @@ BufferPool::Tier& BufferPool::tierFor(std::size_t capacity, VkMemoryPropertyFlag
|
||||
return !sharedTiers() && capacity < classLimit ? smallTier : largeTier;
|
||||
}
|
||||
|
||||
std::optional<BufferAllocation> BufferPool::Take(std::size_t bytes, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, const char* category) {
|
||||
std::optional<BufferAllocation> BufferPool::Take(std::size_t bytes, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, const char* category, bool hostPlaced) {
|
||||
static const bool profile = std::getenv("APS5_PROFILE_DRAW") != nullptr;
|
||||
const auto capacity = Capacity(bytes);
|
||||
std::lock_guard lock(mutex);
|
||||
@@ -415,9 +415,9 @@ std::optional<BufferAllocation> BufferPool::Take(std::size_t bytes, VkBufferUsag
|
||||
auto& tier = tierFor(capacity, properties);
|
||||
const auto largest = &tier == &deviceTier && !exactSizes() && bytes <= std::numeric_limits<std::size_t>::max() / 2 ? std::max(capacity, bytes * 2) : capacity;
|
||||
auto found = tier.free.end();
|
||||
for (auto size = capacity; size <= largest && found == tier.free.end(); size = NextCapacity(size)) found = tier.free.find({size, usage, properties});
|
||||
for (auto size = capacity; size <= largest && found == tier.free.end(); size = NextCapacity(size)) found = tier.free.find({size, usage, properties, 0, hostPlaced});
|
||||
if (found == tier.free.end() || found->second.empty()) {
|
||||
++tier.misses;
|
||||
if (!hostPlaced) ++tier.misses;
|
||||
return std::nullopt;
|
||||
}
|
||||
auto& slots = found->second;
|
||||
@@ -497,7 +497,7 @@ VkDeviceSize BufferPool::ReclaimIdleDevice(VkDeviceSize bytes, std::chrono::stea
|
||||
for (auto it = deviceTier.free.begin(); it != deviceTier.free.end(); ++it) {
|
||||
if (it->second.empty()) continue;
|
||||
const auto& slot = it->second.front();
|
||||
if (slot.allocation.buffer == VK_NULL_HANDLE || slot.allocation.slab || slot.lastUse > reclaimBefore) continue;
|
||||
if (slot.allocation.buffer == VK_NULL_HANDLE || slot.allocation.slab || slot.allocation.hostPlaced || slot.lastUse > reclaimBefore) continue;
|
||||
if (oldest == deviceTier.free.end() || slot.lastUse < oldest->second.front().lastUse) oldest = it;
|
||||
}
|
||||
if (oldest == deviceTier.free.end()) {
|
||||
@@ -586,7 +586,7 @@ void BufferPool::Put(const BufferAllocation& allocation) noexcept {
|
||||
evicted.push_back(allocation);
|
||||
} else {
|
||||
while (tier.slots != 0 && (tier.retainedBytes + allocation.allocationBytes > tier.budget || tier.slots >= maxSlots)) evictOldest(tier, evicted);
|
||||
tier.free[{allocation.bytes, allocation.usage, allocation.properties}].push_back({allocation, ++clock, {}});
|
||||
tier.free[{allocation.bytes, allocation.usage, allocation.properties, 0, allocation.hostPlaced}].push_back({allocation, ++clock, {}});
|
||||
++tier.slots;
|
||||
tier.retainedBytes += allocation.allocationBytes;
|
||||
if (allocation.slab) MemoryAccounting::RetainPart(device, allocation.memory, allocation.allocationBytes, true);
|
||||
|
||||
@@ -729,7 +729,7 @@ DccKeys ProvedClearKeys(const GuestTextureResource& resource, std::uint64_t gues
|
||||
// The collect precedes the scan: a write landing between them is stamped above `collected`, so
|
||||
// the proof it would invalidate is never taken as current.
|
||||
const auto collected = count == 0 ? 0 : GuestMemory::CollectWrites(resource.dccAddress, count);
|
||||
if (proof.generation != 0 && collected != 0 && GuestMemory::UnchangedSince(resource.dccAddress, count, proof.generation)) {
|
||||
if (proof.generation != 0 && collected != 0 && GuestMemory::UnchangedSince(resource.dccAddress, count, proof.generation) && PendingKeyProofHolds(resource, guestBytes, proof)) {
|
||||
counters.proved.fetch_add(1, std::memory_order_relaxed);
|
||||
return proof.keys;
|
||||
}
|
||||
@@ -748,12 +748,36 @@ DccKeys ProvedClearKeys(const GuestTextureResource& resource, std::uint64_t gues
|
||||
stable = !Recorder::SnapshotWriteOverlaps(resource.dccAddress, count);
|
||||
}
|
||||
}
|
||||
proof = stable ? DccKeyProof{keys, collected} : DccKeyProof{};
|
||||
proof = stable ? DccKeyProof{keys, collected} : memoized && collected != 0 ? PendingKeyProof(resource, guestBytes, keys) : DccKeyProof{};
|
||||
counters.scanned.fetch_add(1, std::memory_order_relaxed);
|
||||
if (!stable) counters.unstable.fetch_add(1, std::memory_order_relaxed);
|
||||
return keys;
|
||||
}
|
||||
|
||||
DccKeyProof PendingKeyProof(const GuestTextureResource& resource, std::uint64_t guestBytes, DccKeys keys) {
|
||||
const auto count = static_cast<std::size_t>(guestBytes / KeyBytes);
|
||||
if (!KeyFastPath() || resource.dccAddress == 0 || count == 0 || keys == DccKeys::Mixed || keys == DccKeys::Unreadable || !GuestMemory::GpuMutex().HeldByThisThread()) return {};
|
||||
auto* recorder = Recorder::Active();
|
||||
if (recorder == nullptr) return {};
|
||||
const auto info = recorder->DescribePendingWrite(resource.dccAddress, count);
|
||||
if (!info.has_value() || info->signaled) return {};
|
||||
const auto note = recorder->NewestWriteNote(resource.dccAddress, count);
|
||||
if (note == 0) return {};
|
||||
const auto collected = GuestMemory::CollectWrites(resource.dccAddress, count);
|
||||
if (collected == 0) return {};
|
||||
return {keys, collected, note, recorder->Id()};
|
||||
}
|
||||
|
||||
bool PendingKeyProofHolds(const GuestTextureResource& resource, std::uint64_t guestBytes, const DccKeyProof& proof) {
|
||||
if (proof.pendingNote == 0) return true;
|
||||
const auto count = static_cast<std::size_t>(guestBytes / KeyBytes);
|
||||
if (!GuestMemory::GpuMutex().HeldByThisThread()) return false;
|
||||
auto* recorder = Recorder::Active();
|
||||
if (recorder == nullptr || recorder->Id() != proof.pendingRecorder || recorder->NewestWriteNote(resource.dccAddress, count) != proof.pendingNote) return false;
|
||||
const auto info = recorder->DescribePendingWrite(resource.dccAddress, count);
|
||||
return info.has_value() && !info->signaled;
|
||||
}
|
||||
|
||||
DccKeyProofCounts KeyProofCounts() {
|
||||
const auto& counters = Proofs();
|
||||
return {counters.proved.load(std::memory_order_relaxed), counters.scanned.load(std::memory_order_relaxed), counters.unstable.load(std::memory_order_relaxed), counters.rangeProved.load(std::memory_order_relaxed), counters.rangeScanned.load(std::memory_order_relaxed)};
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#include "prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
|
||||
#include "prx/libc/include/GuestAllocations.hpp"
|
||||
#include "prx/libc/include/PrimedSharedMutex.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/BufferPool.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/FirstSampleCopy.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/Recorder.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp"
|
||||
@@ -13,6 +15,7 @@
|
||||
#include "prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/TextureTiling.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Mutex.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/shaders/DepthToStorage_spv.h"
|
||||
#include "RdnaDecoder/RdnaInstructionDecoder.hpp"
|
||||
#include "RdnaDecoder/include/RdnaDecoder/RdnaDescriptorFormat.hpp"
|
||||
#include <algorithm>
|
||||
@@ -74,6 +77,121 @@ bool singleComponent(VkFormat format, std::uint32_t bytes) {
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic<bool> depthTransferPasses{std::getenv("APS5_NO_DEPTH_TRANSFER_PASS") == nullptr};
|
||||
std::atomic<std::uint64_t> depthTransferPassCount{0};
|
||||
|
||||
bool depthToStoragePass(const Context& context, VkFormat depthFormat, VkFormat colorFormat) {
|
||||
if (!context.pushDescriptors || !depthTransferPasses.load(std::memory_order_relaxed)) return false;
|
||||
return aspectCopyBytes(depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT) == 4 && singleComponent(colorFormat, 4);
|
||||
}
|
||||
|
||||
struct RectPush {
|
||||
std::array<std::uint32_t, 2> offset;
|
||||
std::array<std::uint32_t, 2> extent;
|
||||
};
|
||||
|
||||
class DepthToStoragePass {
|
||||
public:
|
||||
explicit DepthToStoragePass(const Context& context) : context(context) {
|
||||
this->context.bufferPool.reset();
|
||||
try {
|
||||
pushSet = context.Function<PFN_vkCmdPushDescriptorSetKHR>("vkCmdPushDescriptorSetKHR");
|
||||
const std::array<VkDescriptorSetLayoutBinding, 2> bindings{{{0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, {1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}}};
|
||||
VkDescriptorSetLayoutCreateInfo setInfo{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO};
|
||||
setInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
|
||||
setInfo.bindingCount = static_cast<std::uint32_t>(bindings.size());
|
||||
setInfo.pBindings = bindings.data();
|
||||
Check(context.Function<PFN_vkCreateDescriptorSetLayout>("vkCreateDescriptorSetLayout")(context.device, &setInfo, nullptr, &setLayout), "vkCreateDescriptorSetLayout depth to storage");
|
||||
const VkPushConstantRange rect{VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(RectPush)};
|
||||
VkPipelineLayoutCreateInfo layoutInfo{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
|
||||
layoutInfo.setLayoutCount = 1;
|
||||
layoutInfo.pSetLayouts = &setLayout;
|
||||
layoutInfo.pushConstantRangeCount = 1;
|
||||
layoutInfo.pPushConstantRanges = ▭
|
||||
Check(context.Function<PFN_vkCreatePipelineLayout>("vkCreatePipelineLayout")(context.device, &layoutInfo, nullptr, &layout), "vkCreatePipelineLayout depth to storage");
|
||||
const auto compute = CreateShaderModule(context, DEPTH_TO_STORAGE_SPV, sizeof(DEPTH_TO_STORAGE_SPV), "vkCreateShaderModule depth to storage");
|
||||
VkComputePipelineCreateInfo info{VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO};
|
||||
info.stage = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, VK_SHADER_STAGE_COMPUTE_BIT, compute, "main", nullptr};
|
||||
info.layout = layout;
|
||||
VkResult created;
|
||||
{
|
||||
auto pipelineCacheLock = context.LockPipelineCacheForUse();
|
||||
created = context.Function<PFN_vkCreateComputePipelines>("vkCreateComputePipelines")(context.device, context.pipelineCache, 1, &info, nullptr, &pipeline);
|
||||
}
|
||||
context.Function<PFN_vkDestroyShaderModule>("vkDestroyShaderModule")(context.device, compute, nullptr);
|
||||
Check(created, "vkCreateComputePipelines depth to storage");
|
||||
} catch (...) {
|
||||
release();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
~DepthToStoragePass() { release(); }
|
||||
DepthToStoragePass(const DepthToStoragePass&) = delete;
|
||||
DepthToStoragePass& operator=(const DepthToStoragePass&) = delete;
|
||||
|
||||
VkDevice Device() const { return context.device; }
|
||||
|
||||
void Record(VkCommandBuffer commands, VkImageView depthPlane, VkImageView texels, std::span<const VkRect2D> rects) const {
|
||||
const VkDescriptorImageInfo depthInfo{VK_NULL_HANDLE, depthPlane, VK_IMAGE_LAYOUT_GENERAL};
|
||||
const VkDescriptorImageInfo texelInfo{VK_NULL_HANDLE, texels, VK_IMAGE_LAYOUT_GENERAL};
|
||||
const std::array<VkWriteDescriptorSet, 2> writes{imageWrite(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, depthInfo), imageWrite(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, texelInfo)};
|
||||
context.Resolved(&DeviceFunctions::cmdBindPipeline, "vkCmdBindPipeline")(commands, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
|
||||
pushSet(commands, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, static_cast<std::uint32_t>(writes.size()), writes.data());
|
||||
const auto pushConstants = context.Resolved(&DeviceFunctions::cmdPushConstants, "vkCmdPushConstants");
|
||||
const auto dispatch = context.Resolved(&DeviceFunctions::cmdDispatch, "vkCmdDispatch");
|
||||
for (const auto& rect : rects) {
|
||||
const RectPush push{{static_cast<std::uint32_t>(rect.offset.x), static_cast<std::uint32_t>(rect.offset.y)}, {rect.extent.width, rect.extent.height}};
|
||||
pushConstants(commands, layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push), &push);
|
||||
dispatch(commands, (rect.extent.width + 7u) / 8u, (rect.extent.height + 7u) / 8u, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static VkWriteDescriptorSet imageWrite(std::uint32_t binding, VkDescriptorType type, const VkDescriptorImageInfo& info) {
|
||||
VkWriteDescriptorSet write{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET};
|
||||
write.dstBinding = binding;
|
||||
write.descriptorCount = 1;
|
||||
write.descriptorType = type;
|
||||
write.pImageInfo = &info;
|
||||
return write;
|
||||
}
|
||||
|
||||
void release() noexcept {
|
||||
context.Function<PFN_vkDestroyPipeline>("vkDestroyPipeline")(context.device, pipeline, nullptr);
|
||||
context.Function<PFN_vkDestroyPipelineLayout>("vkDestroyPipelineLayout")(context.device, layout, nullptr);
|
||||
context.Function<PFN_vkDestroyDescriptorSetLayout>("vkDestroyDescriptorSetLayout")(context.device, setLayout, nullptr);
|
||||
pipeline = VK_NULL_HANDLE;
|
||||
layout = VK_NULL_HANDLE;
|
||||
setLayout = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
Context context;
|
||||
PFN_vkCmdPushDescriptorSetKHR pushSet = nullptr;
|
||||
VkDescriptorSetLayout setLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout layout = VK_NULL_HANDLE;
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
std::mutex& depthToStoragePassesMutex() {
|
||||
static std::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<DepthToStoragePass>>& depthToStoragePasses() {
|
||||
static auto* list = new std::vector<std::unique_ptr<DepthToStoragePass>>();
|
||||
return *list;
|
||||
}
|
||||
|
||||
DepthToStoragePass& depthToStoragePassFor(const Context& context) {
|
||||
std::lock_guard lock(depthToStoragePassesMutex());
|
||||
auto& list = depthToStoragePasses();
|
||||
for (const auto& pass : list) {
|
||||
if (pass->Device() == context.device) return *pass;
|
||||
}
|
||||
list.push_back(std::make_unique<DepthToStoragePass>(context));
|
||||
return *list.back();
|
||||
}
|
||||
|
||||
struct DepthGuard {
|
||||
VkDevice device;
|
||||
std::uint64_t address;
|
||||
@@ -84,7 +202,7 @@ struct DepthGuard {
|
||||
};
|
||||
|
||||
std::shared_mutex& depthGuardMutex() {
|
||||
static std::shared_mutex mutex;
|
||||
static PrimedSharedMutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
@@ -100,6 +218,8 @@ std::atomic<bool>& anyDepthGuard() {
|
||||
|
||||
struct DepthSamplingState {
|
||||
std::vector<GuestMemory::UnchangedQuery> initial;
|
||||
std::optional<float> initialDepth;
|
||||
std::optional<std::uint8_t> initialStencil;
|
||||
std::string refusal;
|
||||
std::optional<std::uint8_t> aliasStencil;
|
||||
std::optional<MultisampleColorAlias> unprovenStencil;
|
||||
@@ -152,6 +272,68 @@ std::uint64_t fillNoteAfter(const Recorder& recorder, const GuestMemory::Unchang
|
||||
return found;
|
||||
}
|
||||
|
||||
bool uniformPlaneTarget(const DepthTarget& target) {
|
||||
return target.format == VK_FORMAT_D32_SFLOAT_S8_UINT && target.stencilAddress != 0u && target.htileAddress == 0u;
|
||||
}
|
||||
|
||||
template <typename Element>
|
||||
std::optional<Element> uniformPlaneValue(std::uint64_t address, std::size_t bytes) {
|
||||
std::array<Element, 16384> chunk{};
|
||||
std::optional<Element> value;
|
||||
for (std::size_t offset = 0u; offset < bytes;) {
|
||||
const auto count = std::min(chunk.size(), (bytes - offset) / sizeof(Element));
|
||||
const auto elements = std::span(chunk).first(count);
|
||||
GuestMemory::Read(address + offset, std::as_writable_bytes(elements));
|
||||
if (!value) value = elements.front();
|
||||
if (std::ranges::any_of(elements, [&](Element element) { return element != *value; })) return std::nullopt;
|
||||
offset += count * sizeof(Element);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
DepthSamplingState prepareUniformPlaneSampling(const Context& context, const DepthTarget& target, DepthSamplingState state) {
|
||||
const auto refuse = [&](const char* reason) {
|
||||
state.refusal = reason;
|
||||
return state;
|
||||
};
|
||||
if (target.depthSwizzle != 24u || target.firstSlice != 0u || target.lastSlice != 0u) return refuse("native multisample depth arrays or non-Z_X layout are not implemented");
|
||||
if ((target.pipeBankXor & ~0xcf00u) != 0u) return refuse("unsupported native multisample depth XOR");
|
||||
if (target.address == 0u || (target.address & 65535u) != 0u || (target.stencilAddress & 65535u) != 0u) return refuse("native multisample depth base is not aligned");
|
||||
if (target.htileStencil) return refuse("native multisample stencil import is not implemented");
|
||||
state.initial = {{target.address, static_cast<std::size_t>(MultisampledDepthBytes_nid_no_patch(target.extent, 4u, target.samples)), 0u}, {target.stencilAddress, static_cast<std::size_t>(MultisampledDepthBytes_nid_no_patch(target.extent, 1u, target.samples)), 0u}};
|
||||
for (const auto& range : state.initial) {
|
||||
if (range.address > std::numeric_limits<std::uint64_t>::max() - range.bytes) return refuse("native depth import range overflows");
|
||||
if (!GuestMemory::Accessible(reinterpret_cast<const void*>(range.address), range.bytes) || !GuestMemory::Watched(range.address, range.bytes)) return refuse("native multisample depth import requires watched accessible guest memory");
|
||||
}
|
||||
const auto& depth = state.initial[0];
|
||||
const auto& stencil = state.initial[1];
|
||||
if (depth.address + depth.bytes > stencil.address && stencil.address + stencil.bytes > depth.address) return refuse("native depth and stencil initial ranges overlap");
|
||||
for (std::size_t index = 0u; index < state.initial.size(); ++index) {
|
||||
const auto alias = MultisampleColorTargetOver(state.initial[index].address, state.initial[index].bytes);
|
||||
if (!alias) continue;
|
||||
reportAlias(*alias, state.initial[index], index == 1u ? "stencil plane" : "depth");
|
||||
return refuse(index == 1u ? stencilAliasRefusal : depthAliasRefusal);
|
||||
}
|
||||
for (auto& range : state.initial) {
|
||||
if (auto* recorder = RecorderFor(context)) recorder->SyncThrough(range.address, range.bytes);
|
||||
StorageTexture::FlushPending(range.address, range.bytes);
|
||||
GuestMemory::FlushGpuWrites(range.address, range.bytes);
|
||||
if (!GuestMemory::Accessible(reinterpret_cast<const void*>(range.address), range.bytes) || !GuestMemory::Watched(range.address, range.bytes)) return refuse("native multisample depth import requires watched accessible guest memory");
|
||||
range.generation = GuestMemory::CollectWritesUncached(range.address, range.bytes);
|
||||
if (range.generation == 0u) return refuse("native multisample depth import requires tracked generations");
|
||||
}
|
||||
const auto depthWord = uniformPlaneValue<std::uint32_t>(depth.address, depth.bytes);
|
||||
const auto depthValue = depthWord ? std::bit_cast<float>(*depthWord) : 0.0f;
|
||||
if (!depthWord || !(depthValue >= 0.0f && depthValue <= 1.0f)) return refuse("native multisample depth plane without HTILE does not hold one depth value in [0, 1]");
|
||||
const auto stencilByte = uniformPlaneValue<std::uint8_t>(stencil.address, stencil.bytes);
|
||||
if (!stencilByte) return refuse("native multisample stencil plane without HTILE does not hold one stencil value");
|
||||
for (const auto& range : state.initial) GuestMemory::CollectWritesUncached(range.address, range.bytes);
|
||||
if (!GuestMemory::UnchangedSinceAll(state.initial)) return refuse("guest writes raced native multisample depth import");
|
||||
state.initialDepth = depthValue;
|
||||
state.initialStencil = *stencilByte;
|
||||
return state;
|
||||
}
|
||||
|
||||
DepthSamplingState prepareDepthSampling(const Context& context, const DepthTarget& target) {
|
||||
DepthSamplingState state;
|
||||
const auto refuse = [&](const char* reason) {
|
||||
@@ -159,6 +341,7 @@ DepthSamplingState prepareDepthSampling(const Context& context, const DepthTarge
|
||||
return state;
|
||||
};
|
||||
if (target.samples != 2u && target.samples != 4u && target.samples != 8u) return refuse("unsupported native depth sample count");
|
||||
if (uniformPlaneTarget(target)) return prepareUniformPlaneSampling(context, target, std::move(state));
|
||||
const bool stencil = target.format == VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
const bool stencilPlane = stencil && !target.htileStencil && target.htileDepthOnly;
|
||||
if (target.format != VK_FORMAT_D16_UNORM && target.format != VK_FORMAT_D32_SFLOAT && !stencil) return refuse("native multisample stencil or depth format import is not implemented");
|
||||
@@ -337,6 +520,10 @@ std::optional<DepthPlaneOverwrite> decodeOverwrite(const StorageImageClear& clea
|
||||
return overwrite;
|
||||
}
|
||||
|
||||
class DepthSurface;
|
||||
std::pair<std::uint64_t, std::uint64_t> staleStencilRange(const DepthSurface& surface);
|
||||
void noteStalePlane(std::uint64_t begin, std::uint64_t end);
|
||||
|
||||
class DepthSurface {
|
||||
public:
|
||||
DepthSurface(const Context& context, const DepthTarget& target, DepthSamplingState sampling = {}) : context(context), target(target), hostFormat(HostDepthFormat(context, target.format)), sampling(std::move(sampling)) {
|
||||
@@ -410,7 +597,7 @@ public:
|
||||
toGeneral.subresourceRange = viewInfo.subresourceRange;
|
||||
const auto barrier = context.Resolved(&DeviceFunctions::cmdPipelineBarrier, "vkCmdPipelineBarrier");
|
||||
barrier(commands, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &toGeneral);
|
||||
const VkClearDepthStencilValue clear{target.clearDepth, this->sampling.aliasStencil.value_or(target.clearStencil)};
|
||||
const VkClearDepthStencilValue clear{this->sampling.initialDepth.value_or(target.clearDepth), this->sampling.initialStencil.value_or(this->sampling.aliasStencil.value_or(target.clearStencil))};
|
||||
context.Function<PFN_vkCmdClearDepthStencilImage>("vkCmdClearDepthStencilImage")(commands, image, VK_IMAGE_LAYOUT_GENERAL, &clear, 1, &toGeneral.subresourceRange);
|
||||
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
|
||||
if (batch) batch->SubmitAndWait();
|
||||
@@ -449,8 +636,9 @@ public:
|
||||
if (!alias || (index == 2u && sampling.unprovenStencil && stencilClearGeneration == 0u)) continue;
|
||||
const auto value = index == 2u && separatePlane ? aliasedStencil(*alias, range, target.samples) : std::nullopt;
|
||||
const bool kept = value.has_value() && (stencilClearGeneration != 0u ? *value == *stencilClearValue : value == sampling.aliasStencil);
|
||||
if (!kept) reportAlias(*alias, range, index == 2u ? "stencil plane" : index == 1u ? "HTILE" : "depth");
|
||||
Require(kept, index == 2u ? stencilAliasRefusal : depthAliasRefusal);
|
||||
const bool stencilRange = index == 2u || (index == 1u && uniformPlaneTarget(target));
|
||||
if (!kept) reportAlias(*alias, range, stencilRange ? "stencil plane" : index == 1u ? "HTILE" : "depth");
|
||||
Require(kept, stencilRange ? stencilAliasRefusal : depthAliasRefusal);
|
||||
planeAliased = true;
|
||||
}
|
||||
if (stencilClearGeneration != 0u) {
|
||||
@@ -507,6 +695,10 @@ public:
|
||||
const bool identity = stencil ? resource.format == 5u : resource.baseAddress == target.address && resource.format == (target.format == VK_FORMAT_D16_UNORM ? 7u : 22u);
|
||||
Require(identity && resource.width == target.extent.width && resource.height == target.extent.height && resource.samples == target.samples, "native multisample depth sampled identity or format mismatch");
|
||||
Require(resource.dimension == TextureDimension::k2DMsaa && resource.tileMode == TextureTileMode::kZ64KBX && resource.depthOrLastArray == 0u && resource.baseArray == 0u && resource.baseLevel == 0u && resource.lastLevel == 0u && resource.mipCount == 1u && resource.allocatedMipCount == 1u && resource.minLod == 0u, "native multisample depth sampled array, mip or layout is not implemented");
|
||||
if (uniformPlaneTarget(target)) {
|
||||
Require(resource.pipeBankXor == target.pipeBankXor && resource.dccAddress == 0u && !resource.dccAlphaOnMsb, "native multisample depth sampled metadata or XOR mismatch");
|
||||
return;
|
||||
}
|
||||
const bool htile = resource.dccAddress == target.htileAddress && resource.dccPipeAligned == target.htilePipeAligned;
|
||||
const bool bare = resource.dccAddress == 0u && !resource.dccPipeAligned;
|
||||
if (stencil) {
|
||||
@@ -629,21 +821,48 @@ public:
|
||||
return texture;
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> FirstSample(const Texture& source, VkComponentMapping components) {
|
||||
auto* recorder = RecorderFor(context);
|
||||
Require(recorder != nullptr, "a native multisampled depth target is sampled only by recorded draws and dispatches");
|
||||
const bool d16 = target.format == VK_FORMAT_D16_UNORM || target.format == VK_FORMAT_D16_UNORM_S8_UINT;
|
||||
const auto format = d16 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R32_SFLOAT;
|
||||
if (firstSample == nullptr) firstSample = std::make_shared<FirstSampleTextures>(context, format, target.extent);
|
||||
firstSample->copy.Record(*recorder, source.View(), source.Layout());
|
||||
const std::array<std::uint32_t, 4> key{static_cast<std::uint32_t>(components.r), static_cast<std::uint32_t>(components.g), static_cast<std::uint32_t>(components.b), static_cast<std::uint32_t>(components.a)};
|
||||
auto& texture = firstSample->textures[key];
|
||||
if (texture == nullptr) {
|
||||
texture = std::make_shared<Texture>(context, firstSample->copy.Image(), format, VK_IMAGE_ASPECT_COLOR_BIT, components);
|
||||
texture->MarkRefreshedPerUse();
|
||||
}
|
||||
return {firstSample, texture.get()};
|
||||
}
|
||||
|
||||
void ForgetClear(VkImageAspectFlags aspects) {
|
||||
pendingClear &= ~aspects;
|
||||
if ((aspects & VK_IMAGE_ASPECT_DEPTH_BIT) != 0) depthFill.reset();
|
||||
if ((aspects & VK_IMAGE_ASPECT_STENCIL_BIT) != 0) stencilFill.reset();
|
||||
}
|
||||
|
||||
void MarkStencilStale() {
|
||||
if (!StencilMirrorable()) return;
|
||||
stencilStale = true;
|
||||
const auto [begin, end] = staleStencilRange(*this);
|
||||
noteStalePlane(begin, end);
|
||||
}
|
||||
|
||||
void NoteHtileClear(VkImageAspectFlags aspects) {
|
||||
ForgetClear(aspects);
|
||||
pendingClear |= aspects;
|
||||
if ((aspects & VK_IMAGE_ASPECT_STENCIL_BIT) != 0u) MarkStencilStale();
|
||||
}
|
||||
|
||||
void NotePlaneFill(VkImageAspectFlagBits aspect, float depth, std::uint8_t stencil) {
|
||||
pendingClear |= aspect;
|
||||
if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) depthFill = depth;
|
||||
else stencilFill = stencil;
|
||||
else {
|
||||
stencilFill = stencil;
|
||||
MarkStencilStale();
|
||||
}
|
||||
}
|
||||
|
||||
void CopyAspectFrom(const DepthSurface& source, VkImageAspectFlagBits aspect) {
|
||||
@@ -861,6 +1080,7 @@ public:
|
||||
auto& plane = stencil ? stencilPlane : depthPlane;
|
||||
const auto source = std::const_pointer_cast<StorageTexture>(candidate.shared_from_this());
|
||||
copyPlane(plane, source, stencil, false);
|
||||
ForgetClear(stencil ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
written = ++depthWrites;
|
||||
NoteHostWrite();
|
||||
return true;
|
||||
@@ -1214,11 +1434,18 @@ private:
|
||||
bool filled = false;
|
||||
};
|
||||
std::map<std::array<std::uint32_t, 13>, std::shared_ptr<Texture>> textures;
|
||||
struct FirstSampleTextures {
|
||||
FirstSampleTextures(const Context& context, VkFormat format, VkExtent2D extent) : copy(context, format, extent) {}
|
||||
FirstSampleCopy copy;
|
||||
std::map<std::array<std::uint32_t, 4>, std::shared_ptr<Texture>> textures;
|
||||
};
|
||||
std::shared_ptr<FirstSampleTextures> firstSample;
|
||||
PlaneStorage depthPlane;
|
||||
PlaneStorage stencilPlane;
|
||||
std::uint64_t depthMemory = 0;
|
||||
std::uint64_t stencilMemory = 0;
|
||||
StencilCopy stencilCopy;
|
||||
VkImageView transferView = VK_NULL_HANDLE;
|
||||
|
||||
void createSampleShadow() {
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
@@ -1407,7 +1634,8 @@ private:
|
||||
const auto bytes = static_cast<std::size_t>(target.extent.width) * target.extent.height * texelBytes;
|
||||
const auto aspect = stencil ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
const bool direct = !stencil && DirectDepthCopy(context, hostFormat, aspect, storage->ImageFormat());
|
||||
if (!direct && plane.staging == nullptr) plane.staging = std::make_unique<DeviceBuffer>(context, bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
const bool passes = toStorage && !stencil && target.samples == 1 && depthToStoragePass(context, hostFormat, storage->ImageFormat());
|
||||
if (!direct && !passes && plane.staging == nullptr) plane.staging = std::make_unique<DeviceBuffer>(context, bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
const auto commands = recorder != nullptr ? recorder->Commands() : batch->Handle();
|
||||
if (recorder != nullptr) recorder->Keep(storage);
|
||||
const std::uint32_t timing = recorder != nullptr ? recorder->BeginGpuTiming(Recorder::CommandClass::Copy) : 0u;
|
||||
@@ -1428,6 +1656,22 @@ private:
|
||||
moved += static_cast<std::size_t>(rect.extent.width) * rect.extent.height * texelBytes;
|
||||
}
|
||||
}
|
||||
if (passes) {
|
||||
const std::vector<VkRect2D> whole{{{0, 0}, target.extent}};
|
||||
const auto& areas = rects != nullptr ? *rects : whole;
|
||||
const auto texels = storage->AtomicView(0, storage->Descriptor().dimension == TextureDimension::k2DArray);
|
||||
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_MEMORY_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
|
||||
depthToStoragePassFor(context).Record(commands, depthTransferView(), texels, areas);
|
||||
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
|
||||
depthTransferPassCount.fetch_add(1, std::memory_order_relaxed);
|
||||
if (batch) {
|
||||
batch->SubmitAndWait();
|
||||
return;
|
||||
}
|
||||
Recorder::CountBarriers(Recorder::CommandClass::Copy, 2);
|
||||
recorder->EndGpuTiming(timing, moved);
|
||||
return;
|
||||
}
|
||||
auto colorRegions = planeRegions;
|
||||
for (auto& region : colorRegions) region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
const auto count = static_cast<std::uint32_t>(planeRegions.size());
|
||||
@@ -1465,6 +1709,17 @@ private:
|
||||
recorder->EndGpuTiming(timing, moved);
|
||||
}
|
||||
|
||||
VkImageView depthTransferView() {
|
||||
if (transferView != VK_NULL_HANDLE) return transferView;
|
||||
VkImageViewCreateInfo info{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
info.image = image;
|
||||
info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
info.format = hostFormat;
|
||||
info.subresourceRange = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1};
|
||||
Check(context.Function<PFN_vkCreateImageView>("vkCreateImageView")(context.device, &info, nullptr, &transferView), "vkCreateImageView depth to storage");
|
||||
return transferView;
|
||||
}
|
||||
|
||||
void release() noexcept {
|
||||
depthPlane = {};
|
||||
stencilPlane = {};
|
||||
@@ -1472,6 +1727,8 @@ private:
|
||||
mirrorPlane = {};
|
||||
stencilMirror = {};
|
||||
textures.clear();
|
||||
if (transferView) context.Function<PFN_vkDestroyImageView>("vkDestroyImageView")(context.device, transferView, nullptr);
|
||||
transferView = VK_NULL_HANDLE;
|
||||
if (view) context.Function<PFN_vkDestroyImageView>("vkDestroyImageView")(context.device, view, nullptr);
|
||||
if (owned != nullptr) owned.reset();
|
||||
else {
|
||||
@@ -2436,6 +2693,10 @@ float HostDepthBiasConstant(const Context& context, VkFormat format, float const
|
||||
}
|
||||
|
||||
VkImageView DepthSurfaceView(const Context& context, const DepthTarget& target, bool depthWritten, bool stencilTested) {
|
||||
return DepthSurfaceViewWithStencilWriteIntent(context, target, depthWritten, stencilTested, true);
|
||||
}
|
||||
|
||||
VkImageView DepthSurfaceViewWithStencilWriteIntent(const Context& context, const DepthTarget& target, bool depthWritten, bool stencilTested, bool stencilWritten) {
|
||||
const auto planeBytes = [&](std::uint32_t bytesPerTexel) { return target.samples == 1u ? DepthSliceBytes(target.extent, bytesPerTexel) : MultisampledDepthBytes_nid_no_patch(target.extent, bytesPerTexel, target.samples); };
|
||||
ClaimMultisampleTargetMemory(target.address, planeBytes(target.format == VK_FORMAT_D16_UNORM || target.format == VK_FORMAT_D16_UNORM_S8_UINT ? 2u : 4u));
|
||||
if (target.stencilAddress != 0u) ClaimMultisampleTargetMemory(target.stencilAddress, planeBytes(1u));
|
||||
@@ -2486,6 +2747,8 @@ VkImageView DepthSurfaceView(const Context& context, const DepthTarget& target,
|
||||
const bool inherits = owner != depthOwners().end() && owner->second.surface->active->load(std::memory_order_acquire) && !owner->second.surface->retired;
|
||||
surface->clearDepth = target.clearDepth;
|
||||
surface->clearStencil = target.clearStencil;
|
||||
const auto stencilOwner = stencilOwners().find({context.device, target.stencilAddress});
|
||||
const bool stencilRebound = stencilOwner == stencilOwners().end() || stencilOwner->second.surface != surface;
|
||||
takePlanes(*surface, created, htileCleared | (cleared ? VK_IMAGE_ASPECT_DEPTH_BIT : 0u));
|
||||
if (cleared || htileCleared != 0u) surface->expanded = false;
|
||||
if (created && !inherits && target.htileAddress == 0) surface->TakeStorage();
|
||||
@@ -2518,11 +2781,7 @@ VkImageView DepthSurfaceView(const Context& context, const DepthTarget& target,
|
||||
surface->MarkAllStale(planeBytes);
|
||||
noteStalePlane(plane, plane + planeBytes);
|
||||
}
|
||||
if (surface->StencilMirrorable()) {
|
||||
surface->stencilStale = true;
|
||||
const auto [begin, end] = staleStencilRange(*surface);
|
||||
noteStalePlane(begin, end);
|
||||
}
|
||||
if (stencilWritten || created || stencilRebound) surface->MarkStencilStale();
|
||||
drawnDepth = surface;
|
||||
return surface->view;
|
||||
}
|
||||
@@ -2900,6 +3159,10 @@ void ClearDepthSurfaces(VkDevice device) {
|
||||
std::erase_if(surfaces(), [&](const auto& surface) { return surface->context.device == device; });
|
||||
std::erase_if(planeCopies(), [&](const auto& entry) { return std::get<0>(entry.first) == device; });
|
||||
std::erase_if(layeredStorages(), [&](const auto& entry) { return std::get<0>(entry.first) == device; });
|
||||
{
|
||||
std::lock_guard passesLock(depthToStoragePassesMutex());
|
||||
std::erase_if(depthToStoragePasses(), [&](const auto& pass) { return pass->Device() == device; });
|
||||
}
|
||||
std::unique_lock guardLock(depthGuardMutex());
|
||||
std::erase_if(depthGuards(), [&](const auto& range) { return range.device == device; });
|
||||
anyDepthGuard().store(!depthGuards().empty(), std::memory_order_release);
|
||||
@@ -2922,6 +3185,16 @@ thread_local bool depthCopySourceActive = false;
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> DepthSurfaceFirstSample(const Context& context, std::span<const std::uint32_t> words, const GuestTextureResource& resource, VkComponentMapping components) {
|
||||
Require(resource.dimension == TextureDimension::k2DMsaa, "reading sample 0 of a depth surface needs a multisampled descriptor");
|
||||
const auto source = DepthSurfaceTexture(context, words, resource, VkComponentMapping{}, VK_IMAGE_VIEW_TYPE_2D);
|
||||
Require(source != nullptr, "reading sample 0 of a multisampled depth surface whose depth plane is not at the descriptor's address is not implemented");
|
||||
std::lock_guard lock(surfacesMutex());
|
||||
auto* found = planeSurface(context.device, resource.baseAddress);
|
||||
Require(found != nullptr && found->target.address == resource.baseAddress, "reading sample 0 of a multisampled depth surface whose depth plane is not at the descriptor's address is not implemented");
|
||||
return found->FirstSample(*source, components);
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> DepthSurfaceTexture(const Context& context, std::span<const std::uint32_t> words, const GuestTextureResource& resource, VkComponentMapping components, VkImageViewType multisampleViewType) {
|
||||
const auto held = [&](const auto& surface) {
|
||||
return surface->active->load(std::memory_order_acquire) && surface->context.device == context.device && !surface->retired && (surface->target.address == resource.baseAddress || (surface->target.stencilAddress != 0 && surface->target.stencilAddress == resource.baseAddress));
|
||||
@@ -2956,7 +3229,9 @@ std::shared_ptr<Texture> DepthSurfaceTexture(const Context& context, std::span<c
|
||||
Recorder::CountBarriers(Recorder::CommandClass::Draw, 1);
|
||||
return found->Sampled(words, resource, components, found == drawnDepth, multisampleViewType, depthCopySourceActive);
|
||||
}
|
||||
if (resource.width != base.extent.width || resource.height != base.extent.height || resource.baseLevel != 0) return nullptr;
|
||||
const bool exact = resource.width == base.extent.width && resource.height == base.extent.height;
|
||||
const bool cropped = !exact && base.gcn && !stencil && found->hostFormat == base.format && (resource.gcnPitch == 0 || resource.gcnPitch == base.extent.width) && resource.width <= base.extent.width && resource.height <= base.extent.height && resource.baseArray == 0 && resource.lastLevel == 0 && resource.dimension == TextureDimension::k2D;
|
||||
if ((!exact && !cropped) || resource.baseLevel != 0) return nullptr;
|
||||
const bool d16 = base.format == VK_FORMAT_D16_UNORM || base.format == VK_FORMAT_D16_UNORM_S8_UINT;
|
||||
const auto format = ResolveTextureFormat(resource.format);
|
||||
const bool depthBits = !stencil && words.size() >= 4 && ShaderRecompiler::DepthBitsTextureWidth(words[1], words[3]) == (d16 ? 16u : 32u);
|
||||
@@ -2964,9 +3239,9 @@ std::shared_ptr<Texture> DepthSurfaceTexture(const Context& context, std::span<c
|
||||
if (!stencil && format != (d16 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R32_SFLOAT) && !depthBits && !integer) return nullptr;
|
||||
const bool cube = resource.dimension == TextureDimension::kCube;
|
||||
const bool layered = cube || (resource.dimension == TextureDimension::k2DArray && resource.depthOrLastArray != 0);
|
||||
const bool sampled = stencil || (!layered && !integer);
|
||||
const bool sampled = !cropped && (stencil || (!layered && !integer));
|
||||
const auto copyFormat = integer ? VK_FORMAT_R16_UINT : d16 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R32_SFLOAT;
|
||||
const bool planes = (format == copyFormat || depthBits) && resource.width == base.extent.width && resource.height == base.extent.height && resource.baseLevel == 0 && resource.lastLevel == 0 && !(resource.baseArray != 0 && (cube || !layered || resource.baseArray > resource.depthOrLastArray)) && !(cube && resource.depthOrLastArray != 0 && (resource.depthOrLastArray + 1u) % 6u != 0u) && (resource.dimension == TextureDimension::k2D || resource.dimension == TextureDimension::k2DArray || cube);
|
||||
const bool planes = (format == copyFormat || depthBits) && resource.lastLevel == 0 && !(resource.baseArray != 0 && (cube || !layered || resource.baseArray > resource.depthOrLastArray)) && !(cube && resource.depthOrLastArray != 0 && (resource.depthOrLastArray + 1u) % 6u != 0u) && (resource.dimension == TextureDimension::k2D || resource.dimension == TextureDimension::k2DArray || cube);
|
||||
if (!(sampled ? found->SampledAccepts(words, resource) : planes) && (found->OverwrittenInMemory() || found->OverwrittenOnGpu())) {
|
||||
retireStoringStale(*found);
|
||||
return nullptr;
|
||||
@@ -2992,10 +3267,11 @@ std::shared_ptr<Texture> DepthSurfaceTexture(const Context& context, std::span<c
|
||||
else slices.push_back({slice->image, slice == drawnDepth ? 0u : slice->written});
|
||||
}
|
||||
const auto imageFormat = integer ? VK_FORMAT_R16_UINT : d16 ? VK_FORMAT_D16_UNORM : VK_FORMAT_D32_SFLOAT;
|
||||
const VkExtent2D extent{resource.width, resource.height};
|
||||
auto& copies = planeCopies();
|
||||
const std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat> copyKey{context.device, base.address, base.extent.width, base.extent.height, imageFormat};
|
||||
const std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat> copyKey{context.device, base.address, extent.width, extent.height, imageFormat};
|
||||
auto& copy = copies[copyKey];
|
||||
if (copy == nullptr || copy->layers < layers) copy = std::make_unique<DepthPlaneCopy>(context, base.extent, imageFormat, layers);
|
||||
if (copy == nullptr || copy->layers < layers) copy = std::make_unique<DepthPlaneCopy>(context, extent, imageFormat, layers);
|
||||
copy->lastUse = ++planeCopyClock();
|
||||
copy->lastPresent = Recorder::Presents();
|
||||
auto texture = copy->Refresh(slices, resource, components, cube || resource.dimension == TextureDimension::k2DArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, layered && !cube ? resource.baseArray : 0u);
|
||||
@@ -3293,4 +3569,12 @@ void SetDirectDepthCopy(bool enabled) {
|
||||
directDepthCopy.store(enabled && std::getenv("APS5_NO_DIRECT_DEPTH_COPY") == nullptr, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void SetDepthTransferPasses(bool enabled) {
|
||||
depthTransferPasses.store(enabled && std::getenv("APS5_NO_DEPTH_TRANSFER_PASS") == nullptr, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::uint64_t DepthTransferPassCount() {
|
||||
return depthTransferPassCount.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -388,8 +388,15 @@ GuestTextureResource ArraySurfaceForTarget(const ColorTarget& color) {
|
||||
|
||||
namespace {
|
||||
|
||||
bool writesStencilTarget(const State& state) {
|
||||
const auto keeps = [](const VkStencilOpState& face) {
|
||||
return face.writeMask == 0u || (face.failOp == VK_STENCIL_OP_KEEP && face.passOp == VK_STENCIL_OP_KEEP && face.depthFailOp == VK_STENCIL_OP_KEEP);
|
||||
};
|
||||
return state.stencilTest && (!keeps(state.stencilFront) || !keeps(state.stencilBack));
|
||||
}
|
||||
|
||||
bool writesDepthTarget(const State& state) {
|
||||
return state.depthWrite || (state.stencilTest && (state.stencilFront.writeMask != 0u || state.stencilBack.writeMask != 0u));
|
||||
return state.depthWrite || writesStencilTarget(state);
|
||||
}
|
||||
|
||||
std::size_t colorKeyCount(const ColorTarget& color, std::size_t bytes) {
|
||||
@@ -1092,7 +1099,7 @@ std::uint32_t CachedFragmentOutputs(const Context& context, std::span<const Comp
|
||||
}
|
||||
std::uint32_t outputs = 0;
|
||||
try {
|
||||
for (const auto location : ValidateShaders(shaders, state, context.subgroup, context.fragmentShaderBarycentric, context.descriptorIndexing, context.imageInt64Atomics, context.geometryShader, context.sampleRateShading, context.bufferInt64Atomics, context.shaderClipDistance, context.shaderCullDistance, context.viewportIndexLayer, context.runtimeDescriptorArray, context.demoteToHelperInvocation, context.shaderTerminateInvocation, context.meshShader)) {
|
||||
for (const auto location : ValidateShaders(shaders, state, context.subgroup, context.fragmentShaderBarycentric, context.descriptorIndexing, context.imageInt64Atomics, context.geometryShader, context.sampleRateShading, context.bufferInt64Atomics, context.shaderClipDistance, context.shaderCullDistance, context.viewportIndexLayer, context.runtimeDescriptorArray, context.demoteToHelperInvocation, context.shaderTerminateInvocation, context.meshShader, context.shaderResourceMinLod)) {
|
||||
Require(location < 32, "fragment output location exceeds the output mask");
|
||||
outputs |= 1u << location;
|
||||
}
|
||||
@@ -1466,7 +1473,7 @@ std::shared_ptr<Buffer> zeroVertexBuffer(const Context& context, std::size_t byt
|
||||
// Draw's validation, index and vertex phases. With `recipe` the fragment outputs, the pipeline
|
||||
// stages and the vertex input layout are the recipe's (derived from the same compiled stages)
|
||||
// instead of computed.
|
||||
DrawInputs prepareDrawInputs(const Context& context, const State& state, const Pm4::DrawParameters& draw, std::span<const CompiledShader> shaders, DrawOutcome& outcome, DrawTimer& timer, const DrawRecipe* recipe) {
|
||||
DrawInputs prepareDrawInputs(const Context& context, const State& state, const Pm4::DrawParameters& draw, std::span<const CompiledShader> shaders, DrawOutcome& outcome, DrawTimer& timer, PerformanceTimer& timing, const DrawRecipe* recipe) {
|
||||
DrawInputs inputs;
|
||||
APS5_LOG_OUT_DEBUG("Draw indices=%u instances=%u indexSize=%u flags=%u indexAddress=0x%llx", draw.indexCount, draw.instanceCount, draw.indexSize, draw.flags, static_cast<unsigned long long>(draw.indexAddress));
|
||||
APS5_LOG_OUT_DEBUG("State colorTarget=%u render=%ux%u colorAddress=0x%llx colorBytes=%llu colorExtent=%ux%u", state.hasColorTarget ? 1u : 0u, state.renderExtent.width, state.renderExtent.height, static_cast<unsigned long long>(state.color.address), static_cast<unsigned long long>(state.color.bytes), state.color.extent.width, state.color.extent.height);
|
||||
@@ -1547,6 +1554,7 @@ DrawInputs prepareDrawInputs(const Context& context, const State& state, const P
|
||||
ValidateDepthBounds(context, state);
|
||||
ValidateSampleMask(context, state, shaders);
|
||||
timer.phase(PhaseValidate);
|
||||
timing.Mark("validate");
|
||||
inputs.maxIndex = draw.indexed ? 0u : draw.firstVertex + draw.indexCount - 1u;
|
||||
if (state.quadList || StripPatches(state, shaders)) {
|
||||
Require(!draw.indirect, state.quadList ? "indirect quad-list draw is unsupported" : "an indirect triangle strip through emulated barycentric patches is unsupported");
|
||||
@@ -1645,7 +1653,7 @@ DrawInputs prepareDrawInputs(const Context& context, const State& state, const P
|
||||
const bool restartLeft = draw.indirect.has_value();
|
||||
auto highest = HighestDrawIndex(kept, draw.indexSize, restartLeft);
|
||||
constexpr std::uint32_t ZeroFetchSlack = 0x10000u;
|
||||
if (const auto zeroFrom = highest ? ZeroFetchVertex(shaders.front().program->vertexAttributes) : std::nullopt) {
|
||||
if (const auto zeroFrom = highest && !shaders.front().program->vertexAttributes.empty() ? ZeroFetchVertex(shaders.front().program->vertexAttributes) : std::nullopt) {
|
||||
const auto limit = *zeroFrom > draw.firstVertex ? *zeroFrom - draw.firstVertex : 0u;
|
||||
if (*highest >= limit && *highest - limit >= ZeroFetchSlack) highest = ClampDrawIndices(kept, draw.indexSize, restartLeft, limit);
|
||||
}
|
||||
@@ -1685,7 +1693,7 @@ DrawInputs prepareDrawInputs(const Context& context, const State& state, const P
|
||||
return inputs;
|
||||
}
|
||||
constexpr std::uint32_t ZeroFetchSlack = 0x10000u;
|
||||
if (const auto zeroFrom = state.stages.mesh ? std::nullopt : ZeroFetchVertex(shaders.front().program->vertexAttributes)) {
|
||||
if (const auto zeroFrom = state.stages.mesh || shaders.front().program->vertexAttributes.empty() ? std::nullopt : ZeroFetchVertex(shaders.front().program->vertexAttributes)) {
|
||||
const auto limit = *zeroFrom > draw.firstVertex ? *zeroFrom - draw.firstVertex : 0u;
|
||||
if (*highest >= limit && *highest - limit >= ZeroFetchSlack) {
|
||||
GuestMemory::FlushGpuWrites(draw.indexAddress, static_cast<std::size_t>(indexBytes));
|
||||
@@ -1719,6 +1727,7 @@ DrawInputs prepareDrawInputs(const Context& context, const State& state, const P
|
||||
}
|
||||
}
|
||||
APS5_LOG_CHARS_OUT_DEBUG("Index validation OK");
|
||||
timing.Mark("index_upload");
|
||||
const auto& attributes = shaders.front().program->vertexAttributes;
|
||||
// Validates the vertex descriptors; the layout also keys and builds the pipeline.
|
||||
if (recipe != nullptr) {
|
||||
@@ -1822,6 +1831,7 @@ DrawInputs prepareDrawInputs(const Context& context, const State& state, const P
|
||||
inputs.vertexOffsets[i] = rangeOffsets[plan.copyOf[j]] + plan.offsets[j];
|
||||
}
|
||||
timer.phase(PhaseVertex);
|
||||
timing.Mark("vertex_upload");
|
||||
return inputs;
|
||||
}
|
||||
|
||||
@@ -2889,6 +2899,10 @@ void rememberShape(const Context& context, std::uint64_t shape, std::span<const
|
||||
choices.insert(choices.begin(), std::move(choice));
|
||||
}
|
||||
|
||||
bool storesIntoResident(const ShaderResources& resources, const StorageTexture& resident) {
|
||||
return std::ranges::any_of(resources.StorageImages(), [&](const std::pair<VkImage, bool>& image) { return image.first == resident.Image() && image.second; });
|
||||
}
|
||||
|
||||
bool prepareDraw(const Context& context, const State& state, const Pm4::DrawParameters& draw, std::span<const CompiledShader> shaders, std::span<const GuestMemorySnapshot> snapshots, PreparedDraw& prepared) {
|
||||
auto*& recipeOut = prepared.recipeOut;
|
||||
auto& stencilReferences = prepared.stencilReferences;
|
||||
@@ -2935,12 +2949,10 @@ bool prepareDraw(const Context& context, const State& state, const Pm4::DrawPara
|
||||
auto& ownWaitedMs = prepared.ownWaitedMs;
|
||||
const auto report = [&](const char* suffix) { reportDrawEnd(state, timer, built, outcome, waitedBefore, ownWaitedMs, suffix); };
|
||||
auto& inputs = prepared.inputs;
|
||||
inputs = prepareDrawInputs(context, state, draw, shaders, outcome, timer, nullptr);
|
||||
inputs = prepareDrawInputs(context, state, draw, shaders, outcome, timer, timing, nullptr);
|
||||
if (inputs.nothing) return false;
|
||||
const auto* args = prepared.args = draw.indirect ? &*draw.indirect : nullptr;
|
||||
const auto indexBytes = inputs.indexBytes;
|
||||
timing.Mark("validate");
|
||||
timing.Mark("index_upload");
|
||||
const int dumpLimit = prepared.dumpLimit = DumpTargetLimit();
|
||||
auto& targets = prepared.targets;
|
||||
targets.resize(state.colors.size());
|
||||
@@ -3065,7 +3077,7 @@ bool prepareDraw(const Context& context, const State& state, const Pm4::DrawPara
|
||||
targetViews.push_back(binding.target->View());
|
||||
}
|
||||
if (state.depth) {
|
||||
targetViews.push_back(DepthSurfaceView(context, *state.depth, state.depthWrite, state.stencilTest));
|
||||
targetViews.push_back(DepthSurfaceViewWithStencilWriteIntent(context, *state.depth, state.depthWrite, state.stencilTest, writesStencilTarget(state)));
|
||||
if (writesDepthTarget(state)) NoteDepthSurfaceWrite(context, *state.depth);
|
||||
}
|
||||
timer.phase(PhasePrepare);
|
||||
@@ -3075,6 +3087,13 @@ bool prepareDraw(const Context& context, const State& state, const Pm4::DrawPara
|
||||
auto& resolved = prepared.resolved;
|
||||
resolved = resolveDrawResources(context, state, draw, shaders, snapshots, indexBytes, recordable, outcome, timer);
|
||||
auto& resources = resolved.resources;
|
||||
for (std::size_t index = 0; index < targets.size(); ++index) {
|
||||
auto& binding = targets[index];
|
||||
if (binding.color.partialWriteMask == 0 || binding.multisampled || binding.resident == nullptr || binding.proxied || storesIntoResident(*resources, *binding.resident)) continue;
|
||||
const auto& color = binding.color;
|
||||
binding.resident = refreshResidentTarget(context, state, color, outcome, profile, [&] { return color.arrayLastSlice != 0 ? CachedStorageLayers(context, ArraySurfaceForTarget(color), color.arraySlice, color.layers) : CachedStorageSurface(context, SurfaceForTarget(color)); });
|
||||
if (binding.resident != nullptr) targetViews[index] = binding.resident->AttachmentView(color.format, color.mip, color.depthSlice, color.layers, color.arraySlice);
|
||||
}
|
||||
if (!stencilReferences.empty() && resources->ChecksFaults()) recordable = false;
|
||||
if (!stencilReferences.empty()) {
|
||||
const auto readImages = resources->StorageImages();
|
||||
@@ -3224,8 +3243,7 @@ bool prepareDraw(const Context& context, const State& state, const Pm4::DrawPara
|
||||
for (const auto& binding : targets) {
|
||||
if (binding.color.partialWriteMask == 0 || binding.multisampled) continue;
|
||||
Require(lean && binding.resident != nullptr && !binding.proxied, "a partial write of a packed color target is merged into its resident image by a recorded draw only");
|
||||
const auto images = resources->StorageImages();
|
||||
Require(std::ranges::any_of(images, [&](const std::pair<VkImage, bool>& image) { return image.first == binding.resident->Image() && image.second; }), "the partial write of a packed color target does not store into the target's resident image");
|
||||
Require(storesIntoResident(*resources, *binding.resident), "the partial write of a packed color target does not store into the target's resident image");
|
||||
}
|
||||
if (!lean && !resolved.moved.empty()) {
|
||||
resolved.resources = std::make_shared<ShaderResources>(context, shaders, state.color, static_cast<std::uint32_t>(state.colors.size()), draw.indexAddress, static_cast<std::size_t>(indexBytes), snapshots);
|
||||
@@ -3805,7 +3823,7 @@ DrawRecipeOutcome DrawWithRecipe(const Context& context, const State& state, con
|
||||
if (recipe.hasDepth != state.depth.has_value()) return miss(DrawRecipeMiss::TargetGone);
|
||||
const std::size_t expectedViews = state.colors.size() + (recipe.hasDepth ? 1u : 0u);
|
||||
Require(recipe.targets.size() == state.colors.size() && recipe.targetViews.size() == expectedViews, "draw recipe targets do not match the state");
|
||||
auto inputs = prepareDrawInputs(context, state, draw, shaders, outcome, timer, &recipe);
|
||||
auto inputs = prepareDrawInputs(context, state, draw, shaders, outcome, timer, timing, &recipe);
|
||||
if (inputs.nothing) {
|
||||
result.recorded = true;
|
||||
return result;
|
||||
@@ -3834,7 +3852,7 @@ DrawRecipeOutcome DrawWithRecipe(const Context& context, const State& state, con
|
||||
}
|
||||
if (recipe.hasDepth) {
|
||||
timer.phase(PhaseSetup);
|
||||
const auto depthView = DepthSurfaceView(context, *state.depth, state.depthWrite, state.stencilTest);
|
||||
const auto depthView = DepthSurfaceViewWithStencilWriteIntent(context, *state.depth, state.depthWrite, state.stencilTest, writesStencilTarget(state));
|
||||
if (writesDepthTarget(state)) NoteDepthSurfaceWrite(context, *state.depth);
|
||||
timer.phase(PhaseReadTarget);
|
||||
if (recipe.targetViews.back() != depthView) return miss(DrawRecipeMiss::TargetGone);
|
||||
|
||||
@@ -32,8 +32,20 @@ struct udmabuf_create {
|
||||
std::uint64_t offset;
|
||||
std::uint64_t size;
|
||||
};
|
||||
struct udmabuf_create_item {
|
||||
std::uint32_t memfd;
|
||||
std::uint32_t pad;
|
||||
std::uint64_t offset;
|
||||
std::uint64_t size;
|
||||
};
|
||||
struct udmabuf_create_list {
|
||||
std::uint32_t flags;
|
||||
std::uint32_t count;
|
||||
udmabuf_create_item list[];
|
||||
};
|
||||
constexpr std::uint32_t UDMABUF_FLAGS_CLOEXEC = 0x01;
|
||||
constexpr unsigned long UDMABUF_CREATE = 0;
|
||||
constexpr unsigned long UDMABUF_CREATE_LIST = 0;
|
||||
#else
|
||||
#include <linux/udmabuf.h>
|
||||
#endif
|
||||
@@ -1499,7 +1511,7 @@ ImportPages importPages(std::uint64_t base, std::uint64_t bytes, bool opening =
|
||||
}
|
||||
const auto protection = info.Protect & 0xffu;
|
||||
const bool pageWritable = (info.Type == MEM_PRIVATE || info.Type == MEM_IMAGE) && writableProtection(protection);
|
||||
const bool pageReadOnly = info.Type != MEM_MAPPED && (protection == PAGE_READONLY || protection == PAGE_EXECUTE_READ);
|
||||
const bool pageReadOnly = (info.Type != MEM_MAPPED || (info.AllocationProtect & 0xffu) == PAGE_READONLY) && (protection == PAGE_READONLY || protection == PAGE_EXECUTE_READ);
|
||||
if (!pageReadOnly) pages.readOnly = false;
|
||||
if (info.Type != MEM_MAPPED) pages.shared = false;
|
||||
if (info.Type != MEM_MAPPED && !pageWritable && !pageReadOnly && pages.refused.BaseAddress == nullptr) pages.refused = info;
|
||||
@@ -1907,6 +1919,12 @@ std::optional<std::uint32_t> hostHeapIndex(const VkPhysicalDeviceMemoryPropertie
|
||||
for (std::uint32_t index = 0; index < memory.memoryHeapCount; ++index) {
|
||||
if ((memory.memoryHeaps[index].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) == 0 && (!heap || memory.memoryHeaps[index].size > memory.memoryHeaps[*heap].size)) heap = index;
|
||||
}
|
||||
if (heap) return heap;
|
||||
constexpr VkMemoryPropertyFlags shared = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||
for (std::uint32_t index = 0; index < std::min<std::uint32_t>(memory.memoryTypeCount, VK_MAX_MEMORY_TYPES); ++index) {
|
||||
const auto candidate = memory.memoryTypes[index].heapIndex;
|
||||
if ((memory.memoryTypes[index].propertyFlags & shared) == shared && candidate < memory.memoryHeapCount && (!heap || memory.memoryHeaps[candidate].size > memory.memoryHeaps[*heap].size)) heap = candidate;
|
||||
}
|
||||
return heap;
|
||||
}
|
||||
|
||||
@@ -3681,7 +3699,7 @@ bool WaitForLeasesAndImports(std::uintptr_t address, std::size_t bytes) {
|
||||
const auto end = static_cast<std::uint64_t>(address) + bytes;
|
||||
auto& imports = Imports();
|
||||
if (releaseParkedImports(imports, address, end)) retiredImport = true;
|
||||
const auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix();
|
||||
const auto lease = GuestAllocations::GuestAllocationsAcquireRegistered_nid_postfix();
|
||||
{
|
||||
std::lock_guard importsLock(imports.mutex);
|
||||
for (auto it = imports.imports.begin(); it != imports.imports.end();) {
|
||||
@@ -3746,7 +3764,7 @@ bool WaitForLeasesAndImports(std::uintptr_t address, std::size_t bytes) {
|
||||
synced = true;
|
||||
drained = true;
|
||||
}
|
||||
const auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix();
|
||||
const auto lease = GuestAllocations::GuestAllocationsAcquireRegistered_nid_postfix();
|
||||
{
|
||||
std::lock_guard importsLock(imports.mutex);
|
||||
for (auto it = imports.imports.begin(); it != imports.imports.end();) {
|
||||
@@ -4524,7 +4542,7 @@ bool ImportMappedRanges(const Context& context, const GuestAllocations::Mapped&
|
||||
bool RegisteredReadableCovers(std::uint64_t address, std::size_t bytes, std::vector<RegisteredPiece>* pieces) {
|
||||
if (pieces != nullptr) pieces->clear();
|
||||
if (bytes == 0 || bytes > std::numeric_limits<std::uint64_t>::max() - address) return false;
|
||||
const auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix();
|
||||
const auto lease = GuestAllocations::GuestAllocationsAcquireRegistered_nid_postfix();
|
||||
const auto end = address + bytes;
|
||||
for (auto at = address; at < end;) {
|
||||
const auto* range = containingRange(lease, at, at + 1);
|
||||
@@ -4537,7 +4555,7 @@ bool RegisteredReadableCovers(std::uint64_t address, std::size_t bytes, std::vec
|
||||
|
||||
std::uint64_t RegisteredReadableEnd(std::uint64_t address) {
|
||||
if (address == std::numeric_limits<std::uint64_t>::max()) return 0;
|
||||
const auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix();
|
||||
const auto lease = GuestAllocations::GuestAllocationsAcquireRegistered_nid_postfix();
|
||||
const auto* range = containingRange(lease, address, address + 1);
|
||||
return range != nullptr ? range->address + range->bytes : 0;
|
||||
}
|
||||
@@ -5325,8 +5343,13 @@ std::uint64_t gpuCopyLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
VkBufferUsageFlags gpuCopyUsage(bool addressable) {
|
||||
return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | (addressable ? VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT : 0u);
|
||||
bool changedCopyBacks(const Context& context) {
|
||||
static const bool disabled = std::getenv("APS5_NO_CHANGED_COPY_BACK") != nullptr;
|
||||
return !disabled && context.bufferDeviceAddress;
|
||||
}
|
||||
|
||||
VkBufferUsageFlags gpuCopyUsage(const Context& context, bool addressable) {
|
||||
return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | (addressable || changedCopyBacks(context) ? VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT : 0u);
|
||||
}
|
||||
|
||||
// Device-local staging. A written V# element bound in place makes the shader store into host
|
||||
@@ -5345,10 +5368,11 @@ VkBufferUsageFlags gpuCopyUsage(bool addressable) {
|
||||
// (resolveOverlays), and AddressRanges cuts the import's range around it so that its pointers reach
|
||||
// the shadow as its descriptor does. The
|
||||
// shadow is per use, not resident: a reused build records its copy-in anew (RecordStagingCopies).
|
||||
// Accepted trade-off, as for the misaligned copies above: a CPU write into a staged range between
|
||||
// the copy-in and the copy-back is rolled back by the copy-back (the whole written element range,
|
||||
// since store extents are not known), for the batch's latency; the staging window keeps the
|
||||
// exposure to the elements named on the [buffers] staging line and APS5_TRACE_STAGING.
|
||||
// Accepted trade-off, as for the misaligned copies above: the copy-back stores only the bytes the
|
||||
// shader changed where the import still holds the copy-in (RecordChangedCopy), but a CPU write
|
||||
// between the copy-in and the copy-back is rolled back at the unaligned ends of a range, in a region
|
||||
// that is not 4-byte aligned and without a shadow copy; the staging window keeps the exposure to
|
||||
// the elements named on the [buffers] staging line and APS5_TRACE_STAGING.
|
||||
// APS5_NO_WRITTEN_SHADOW=1 and APS5_NO_ATOMIC_STAGING=1 bind those elements in place as before;
|
||||
// APS5_WRITTEN_SHADOW_MIN_KIB / APS5_WRITTEN_SHADOW_MAX_KIB (16 / 2048, 8192 on a discrete GPU) bound
|
||||
// the written window: on an integrated GPU a kernel streaming once through a large buffer (the
|
||||
@@ -5432,7 +5456,11 @@ CopyStats& Copies() {
|
||||
// region takes the path it would take without staging (Region::unstaged).
|
||||
std::shared_ptr<Buffer> stagingBuffer(const Context& context, std::size_t bytes, VkBufferUsageFlags usage) {
|
||||
try {
|
||||
return std::make_shared<Buffer>(context, bytes, usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
if (auto buffer = Buffer::WithinDeviceLocalHeadroom(context, bytes, usage)) return buffer;
|
||||
static std::atomic<int> reported{0};
|
||||
if (reported.fetch_add(1, std::memory_order_relaxed) < 4) std::fprintf(stderr, "[buffers] staging shadow of %zu bytes refused: its device-local heap is within an eighth of its budget\n", bytes);
|
||||
Copies().stagingRefused.fetch_add(1, std::memory_order_relaxed);
|
||||
return nullptr;
|
||||
} catch (const std::exception& error) {
|
||||
static std::atomic<int> reported{0};
|
||||
if (reported.fetch_add(1, std::memory_order_relaxed) < 4) std::fprintf(stderr, "[buffers] staging shadow of %zu bytes refused: %s\n", bytes, error.what());
|
||||
@@ -5725,7 +5753,7 @@ void GuestBufferMemory::UploadPrepare(bool addressable) {
|
||||
const bool misaligned = !bindableInPlace(HostImportOffset(*entry, region.begin), addressable);
|
||||
if (staged) {
|
||||
const auto allocateStart = std::chrono::steady_clock::now();
|
||||
region.buffer = stagingBuffer(context, static_cast<std::size_t>(region.end - region.begin), gpuCopyUsage(addressable));
|
||||
region.buffer = stagingBuffer(context, static_cast<std::size_t>(region.end - region.begin), gpuCopyUsage(context, addressable));
|
||||
if (profile) allocateUs.fetch_add(microsecondsSince(allocateStart), std::memory_order_relaxed);
|
||||
if (region.buffer == nullptr) {
|
||||
// No shadow to be had: in place when aligned, else the host copy below.
|
||||
@@ -5737,7 +5765,7 @@ void GuestBufferMemory::UploadPrepare(bool addressable) {
|
||||
if (!staged) {
|
||||
if (!gpuCopyEligible(region)) continue;
|
||||
const auto allocateStart = std::chrono::steady_clock::now();
|
||||
region.buffer = std::make_shared<Buffer>(context, static_cast<std::size_t>(region.end - region.begin), gpuCopyUsage(addressable), copyBufferProperties(false));
|
||||
region.buffer = std::make_shared<Buffer>(context, static_cast<std::size_t>(region.end - region.begin), gpuCopyUsage(context, addressable), copyBufferProperties(false));
|
||||
if (profile) allocateUs.fetch_add(microsecondsSince(allocateStart), std::memory_order_relaxed);
|
||||
}
|
||||
region.deviceLocal = staged;
|
||||
@@ -5957,7 +5985,9 @@ void GuestBufferMemory::UploadFinish(bool addressable, std::optional<std::pair<s
|
||||
copyOnGpu = true;
|
||||
region.deviceLocal = staged;
|
||||
region.copySource = entry->buffer;
|
||||
region.copySourceBase = entry->base - entry->lead;
|
||||
const auto start = HostImportBufferStart(*entry);
|
||||
region.copySourceBase = start.guest;
|
||||
region.copySourceAddress = start.device;
|
||||
}
|
||||
}
|
||||
if (region.direct != nullptr) {
|
||||
@@ -6157,12 +6187,12 @@ void GuestBufferMemory::recordGpuCopies(std::span<Region* const> copies, bool ad
|
||||
if (region->buffer == nullptr) {
|
||||
// Not made by UploadPrepare (the registry was stale then): made here, under the lock.
|
||||
const auto allocateStart = std::chrono::steady_clock::now();
|
||||
if (region->deviceLocal) region->buffer = stagingBuffer(context, static_cast<std::size_t>(bytes), gpuCopyUsage(addressable));
|
||||
if (region->deviceLocal) region->buffer = stagingBuffer(context, static_cast<std::size_t>(bytes), gpuCopyUsage(context, addressable));
|
||||
if (region->buffer == nullptr) {
|
||||
// Or no shadow to be had: a host copy serves the region instead, aligned or not.
|
||||
region->deviceLocal = false;
|
||||
region->unstaged = true;
|
||||
region->buffer = std::make_shared<Buffer>(context, static_cast<std::size_t>(bytes), gpuCopyUsage(addressable), copyBufferProperties(false));
|
||||
region->buffer = std::make_shared<Buffer>(context, static_cast<std::size_t>(bytes), gpuCopyUsage(context, addressable), copyBufferProperties(false));
|
||||
}
|
||||
if (profile) allocateUs.fetch_add(microsecondsSince(allocateStart), std::memory_order_relaxed);
|
||||
}
|
||||
@@ -6225,6 +6255,28 @@ void GuestBufferMemory::recordGpuCopies(std::span<Region* const> copies, bool ad
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<Region*> shadowed;
|
||||
for (auto* region : copies) {
|
||||
const auto bytes = static_cast<std::size_t>(region->end - region->begin);
|
||||
if (!changedCopyBacks(context) || region->buffer->DeviceAddress() == 0 || !WritesOverlap(region->begin, bytes)) {
|
||||
region->shadowCopy = nullptr;
|
||||
continue;
|
||||
}
|
||||
if (region->shadowCopy == nullptr) region->shadowCopy = stagingBuffer(context, bytes, gpuCopyUsage(context, true));
|
||||
if (region->shadowCopy == nullptr || region->shadowCopy->DeviceAddress() == 0) {
|
||||
region->shadowCopy = nullptr;
|
||||
continue;
|
||||
}
|
||||
shadowed.push_back(region);
|
||||
}
|
||||
if (!shadowed.empty()) {
|
||||
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
||||
Recorder::CountBarriers(Recorder::CommandClass::StagingIn);
|
||||
for (auto* region : shadowed) {
|
||||
CopyBuffer(context, commands, region->buffer->Handle(), 0, region->shadowCopy->Handle(), 0, region->end - region->begin);
|
||||
recorder->Keep(region->shadowCopy);
|
||||
}
|
||||
}
|
||||
if (stagedAny) reportStaging();
|
||||
// The copied bytes are visible to the shaders bound to the buffers, which may also store into
|
||||
// them. Every stage: dispatches and draws share this path, and draws run mesh, task and
|
||||
@@ -6283,7 +6335,7 @@ void GuestBufferMemory::RecordCopyBacks(Recorder& recorder) {
|
||||
commands = recorder.Commands(&covered);
|
||||
timing = recorder.BeginGpuTiming(StagingCopyBackKey);
|
||||
// The shader's stores into the buffer (whichever stage made them) precede the copy.
|
||||
constexpr BarrierMask leading{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT};
|
||||
constexpr BarrierMask leading{VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT};
|
||||
if (!Recorder::ElideCovered(Recorder::CommandClass::StagingOut, leading, covered)) {
|
||||
RecordMemoryBarrier(context, commands, leading.srcStage, leading.dstStage, leading.srcAccess, leading.dstAccess);
|
||||
Recorder::CountBarriers(Recorder::CommandClass::StagingOut);
|
||||
@@ -6292,7 +6344,34 @@ void GuestBufferMemory::RecordCopyBacks(Recorder& recorder) {
|
||||
}
|
||||
// Exactly the sub-range the shader may write, in place in the import: what the shader
|
||||
// would have stored there itself had the range been bindable.
|
||||
CopyBuffer(context, commands, region.buffer->Handle(), from - region.begin, region.copySource, from - region.copySourceBase, to - from);
|
||||
auto whole = from;
|
||||
auto wholeEnd = to;
|
||||
if (region.shadowCopy != nullptr && region.copySourceAddress != 0 && region.begin % 4u == 0 && region.copySourceBase % 4u == 0) {
|
||||
const auto alignedFrom = (from + 3u) & ~std::uint64_t{3};
|
||||
const auto alignedTo = to & ~std::uint64_t{3};
|
||||
static const bool traceDivergence = std::getenv("APS5_TRACE_COPY_BACK") != nullptr;
|
||||
std::shared_ptr<Buffer> counter;
|
||||
if (traceDivergence && alignedFrom < alignedTo) {
|
||||
counter = std::make_shared<Buffer>(context, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
std::memset(counter->Bytes().data(), 0, 16);
|
||||
}
|
||||
if (alignedFrom < alignedTo && recorder.RecordChangedCopy(commands, region.buffer->DeviceAddress() + (alignedFrom - region.begin), region.shadowCopy->DeviceAddress() + (alignedFrom - region.begin), region.copySourceAddress + (alignedFrom - region.copySourceBase), static_cast<std::uint32_t>((alignedTo - alignedFrom) / 4u), counter != nullptr ? counter->DeviceAddress() : 0)) {
|
||||
if (counter != nullptr) {
|
||||
recorder.Keep(counter);
|
||||
recorder.OnComplete([counter, alignedFrom, alignedTo, regionBegin = region.begin, regionEnd = region.end] {
|
||||
std::uint32_t diverged = 0;
|
||||
std::memcpy(&diverged, counter->Bytes().data(), sizeof(diverged));
|
||||
static const bool alwaysCopy = std::getenv("APS5_CHANGED_COPY_ALWAYS") != nullptr;
|
||||
if (diverged != 0) std::fprintf(stderr, "[copy-back] 0x%llx+0x%llx (region 0x%llx+0x%llx): %u dwords where the shader and the CPU changed the same bytes; %s\n", static_cast<unsigned long long>(alignedFrom), static_cast<unsigned long long>(alignedTo - alignedFrom), static_cast<unsigned long long>(regionBegin), static_cast<unsigned long long>(regionEnd - regionBegin), diverged, alwaysCopy ? "the shader's bytes were stored (APS5_CHANGED_COPY_ALWAYS)" : "the CPU's bytes were kept");
|
||||
});
|
||||
}
|
||||
if (from < alignedFrom) CopyBuffer(context, commands, region.buffer->Handle(), from - region.begin, region.copySource, from - region.copySourceBase, alignedFrom - from);
|
||||
if (alignedTo < to) CopyBuffer(context, commands, region.buffer->Handle(), alignedTo - region.begin, region.copySource, alignedTo - region.copySourceBase, to - alignedTo);
|
||||
whole = wholeEnd;
|
||||
recorder.Keep(region.shadowCopy);
|
||||
}
|
||||
}
|
||||
if (whole < wholeEnd) CopyBuffer(context, commands, region.buffer->Handle(), whole - region.begin, region.copySource, whole - region.copySourceBase, wholeEnd - whole);
|
||||
copiedBytes += to - from;
|
||||
recorder.Keep(region.buffer);
|
||||
if (profile) {
|
||||
@@ -6312,7 +6391,7 @@ void GuestBufferMemory::RecordCopyBacks(Recorder& recorder) {
|
||||
// indirect dispatch's arguments) and to the host once the batch completed; the caller's
|
||||
// pending-write note makes CPU readers wait for that.
|
||||
constexpr VkAccessFlags copiedAccess = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_HOST_READ_BIT;
|
||||
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, copiedAccess);
|
||||
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | VK_PIPELINE_STAGE_HOST_BIT, VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT, copiedAccess);
|
||||
Recorder::CountBarriers(Recorder::CommandClass::StagingOut);
|
||||
recorder.MarkCovered(copiedAccess);
|
||||
recorder.EndGpuTiming(timing, copiedBytes);
|
||||
@@ -6588,10 +6667,12 @@ void GuestBufferMemory::MarkDirectWrites() const {
|
||||
|
||||
namespace {
|
||||
|
||||
void storeChanged(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original) {
|
||||
using ChangedStore = void (*)(std::uint64_t, std::span<const std::byte>, std::span<const std::byte>);
|
||||
|
||||
void storeChanged(std::uint64_t address, std::span<const std::byte> current, std::span<const std::byte> original, ChangedStore store) {
|
||||
const auto writable = GuestMemory::DescribeCommitted(address, current.size(), true);
|
||||
if (writable.whole) {
|
||||
GuestMemory::WriteChanged(address, current, original);
|
||||
store(address, current, original);
|
||||
return;
|
||||
}
|
||||
const auto unchanged = [&](std::uint64_t from, std::uint64_t to) {
|
||||
@@ -6606,7 +6687,7 @@ void storeChanged(std::uint64_t address, std::span<const std::byte> current, std
|
||||
if (cursor < first) unchanged(cursor, first);
|
||||
const auto at = static_cast<std::size_t>(first - address);
|
||||
const auto length = static_cast<std::size_t>(last - first);
|
||||
GuestMemory::WriteChanged(first, current.subspan(at, length), original.subspan(at, length));
|
||||
store(first, current.subspan(at, length), original.subspan(at, length));
|
||||
cursor = last;
|
||||
}
|
||||
if (cursor < address + current.size()) unchanged(cursor, address + current.size());
|
||||
@@ -6676,7 +6757,8 @@ void GuestBufferMemory::WriteBack() {
|
||||
Require(uploaded && !committed, "guest memory cannot be committed twice or before upload");
|
||||
const auto merged = mergeWrites(writes);
|
||||
// The CPU keeps running while the GPU works, so storing whole ranges would roll back its writes to
|
||||
// bytes the shader never touched. Only runs that differ from the uploaded copy are stored.
|
||||
// bytes the shader never touched. Only runs that differ from the uploaded copy are stored, and a
|
||||
// host copy leaves the bytes the CPU changed since its upload as they are.
|
||||
for (const auto& [begin, end] : merged) {
|
||||
const auto* found = owner(begin, end);
|
||||
Require(found != nullptr, "write-back range has no GPU owner");
|
||||
@@ -6704,7 +6786,7 @@ void GuestBufferMemory::WriteBack() {
|
||||
if (mirror.resident == nullptr) {
|
||||
const auto current = mirror.buffer->Bytes().subspan(offset, length);
|
||||
if (mirror.sparse) storeSparse(mirror, begin, current, reference->second);
|
||||
else storeChanged(begin, current, reference->second);
|
||||
else storeChanged(begin, current, reference->second, GuestMemory::WriteChanged);
|
||||
continue;
|
||||
}
|
||||
std::vector<std::byte> current(length);
|
||||
@@ -6716,7 +6798,7 @@ void GuestBufferMemory::WriteBack() {
|
||||
}
|
||||
mirror.resident->Store(begin, current);
|
||||
if (mirror.sparse) storeSparse(mirror, begin, current, reference->second);
|
||||
else storeChanged(begin, current, reference->second);
|
||||
else storeChanged(begin, current, reference->second, GuestMemory::WriteChanged);
|
||||
continue;
|
||||
}
|
||||
const auto current = mirror.buffer->Bytes().subspan(offset, length);
|
||||
@@ -6752,7 +6834,7 @@ void GuestBufferMemory::WriteBack() {
|
||||
if (!region.sparse) {
|
||||
const auto first = static_cast<std::size_t>(begin - region.begin);
|
||||
const auto length = static_cast<std::size_t>(end - begin);
|
||||
storeChanged(begin, region.buffer->Bytes().subspan(first, length), std::span<const std::byte>(region.uploaded).subspan(first, length));
|
||||
storeChanged(begin, region.buffer->Bytes().subspan(first, length), std::span<const std::byte>(region.uploaded).subspan(first, length), GuestMemory::WriteChangedKeepingGuest);
|
||||
continue;
|
||||
}
|
||||
std::size_t packed = 0;
|
||||
@@ -6761,7 +6843,7 @@ void GuestBufferMemory::WriteBack() {
|
||||
const auto to = std::min(last, end);
|
||||
if (from < to) {
|
||||
const auto length = static_cast<std::size_t>(to - from);
|
||||
storeChanged(from, region.buffer->Bytes().subspan(static_cast<std::size_t>(from - region.begin), length), std::span<const std::byte>(region.uploaded).subspan(packed + static_cast<std::size_t>(from - first), length));
|
||||
storeChanged(from, region.buffer->Bytes().subspan(static_cast<std::size_t>(from - region.begin), length), std::span<const std::byte>(region.uploaded).subspan(packed + static_cast<std::size_t>(from - first), length), GuestMemory::WriteChangedKeepingGuest);
|
||||
}
|
||||
packed += static_cast<std::size_t>(last - first);
|
||||
}
|
||||
|
||||
@@ -172,6 +172,16 @@ GuestSamplerResource DecodeSamplerResource(std::span<const std::uint32_t> words,
|
||||
return result;
|
||||
}
|
||||
|
||||
bool HoldsLodAtZero(std::span<const std::uint32_t, 4> words) {
|
||||
return (words[0] & (1u << 15u)) == 0u && (((words[2] >> 26u) & 3u) == 0u || ((words[1] >> 12u) & 0xfffu) == 0u);
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 4> PinnedLodSamplerWords(std::span<const std::uint32_t, 4> words, std::uint32_t lod) {
|
||||
std::array<std::uint32_t, 4> pinned{words[0], (words[1] & ~0xffffffu) | lod | (lod << 12u), words[2], words[3]};
|
||||
if (((pinned[2] >> 26u) & 3u) == 0u) pinned[2] |= 1u << 26u;
|
||||
return pinned;
|
||||
}
|
||||
|
||||
std::optional<std::array<std::uint32_t, 4>> SingleLevelSamplerWords(std::span<const std::uint32_t, 4> words, bool singleLevelImage, bool mipmappedImage) {
|
||||
const auto filters = words[2];
|
||||
if (((filters >> 29u) & 1u) == 0 || !singleLevelImage || (!isAnisoFilter((filters >> 20u) & 3u) && !isAnisoFilter((filters >> 22u) & 3u))) return std::nullopt;
|
||||
|
||||
Loaded 100 of 1068 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user