Merge branch 'master' into windows-clang

This commit is contained in:
qurious-pixel 2025-10-21 13:47:03 -07:00 committed by Live session user
commit d1e7fe4da0
35 changed files with 271 additions and 144 deletions

View file

@ -24,7 +24,7 @@ env:
jobs: jobs:
Linux_Build: Linux_Build:
# Only run push event on master branch of main repo, but run all PRs # Only run push event on master branch of main repo, but run all PRs
#if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master')
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -117,7 +117,7 @@ jobs:
Mac_Build: Mac_Build:
# Only run push event on master branch of main repo, but run all PRs # Only run push event on master branch of main repo, but run all PRs
#if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master')
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -191,14 +191,14 @@ jobs:
run: .ci/github-upload.sh run: .ci/github-upload.sh
- name: Save Build Ccache - name: Save Build Ccache
#if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main uses: actions/cache/save@main
with: with:
path: ${{ env.CCACHE_DIR }} path: ${{ env.CCACHE_DIR }}
key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }}
- name: Save Qt Cache - name: Save Qt Cache
#if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main uses: actions/cache/save@main
with: with:
path: /tmp/Qt path: /tmp/Qt
@ -206,7 +206,7 @@ jobs:
Windows_Build: Windows_Build:
# Only run push event on master branch of main repo, but run all PRs # Only run push event on master branch of main repo, but run all PRs
#if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master')
name: RPCS3 Windows name: RPCS3 Windows
runs-on: windows-2025 runs-on: windows-2025
env: env:
@ -312,14 +312,14 @@ jobs:
run: .ci/github-upload.sh run: .ci/github-upload.sh
- name: Save Build Ccache - name: Save Build Ccache
#if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main uses: actions/cache/save@main
with: with:
path: ${{ env.CCACHE_DIR }} path: ${{ env.CCACHE_DIR }}
key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }}
- name: Save Dependencies Cache - name: Save Dependencies Cache
#if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main uses: actions/cache/save@main
with: with:
path: ${{ env.DEPS_CACHE_DIR }} path: ${{ env.DEPS_CACHE_DIR }}
@ -327,7 +327,7 @@ jobs:
Windows_Build_Clang: Windows_Build_Clang:
# Only run push event on master branch of main repo, but run all PRs # Only run push event on master branch of main repo, but run all PRs
#if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master')
runs-on: windows-2025 runs-on: windows-2025
strategy: strategy:
fail-fast: false fail-fast: false
@ -415,9 +415,7 @@ jobs:
--clean-after-build --clean-after-build
- name: Save vcpkg cache - name: Save vcpkg cache
if: ${{ matrix.compiler == 'clang-cl' }} if: ${{ github.ref == 'refs/heads/master' && matrix.compiler == 'clang-cl' }}
#if: ${{ !steps.restore-vcpkg-cache.outputs.cache-hit && matrix.compiler == 'clang-cl' }}
#if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main uses: actions/cache/save@main
with: with:
path: | path: |
@ -451,8 +449,7 @@ jobs:
Add-Content -Path $env:GITHUB_PATH -Value "D:\a\rpcs3\rpcs3\llvm-${{ matrix.llvmver }}\bin" Add-Content -Path $env:GITHUB_PATH -Value "D:\a\rpcs3\rpcs3\llvm-${{ matrix.llvmver }}\bin"
C:\PROGRA~1\LLVM\bin\clang-cl.exe --version C:\PROGRA~1\LLVM\bin\clang-cl.exe --version
- name: Save LLVM Cache - name: Save LLVM Cache
if: ${{ matrix.compiler == 'clang-cl' && steps.llvm-cache.outputs.cache-hit != 'true' }} if: ${{ github.ref == 'refs/heads/master' && matrix.compiler == 'clang-cl' }}
#if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main uses: actions/cache/save@main
with: with:
path: ./llvm-${{ matrix.llvmver }} path: ./llvm-${{ matrix.llvmver }}
@ -473,6 +470,8 @@ jobs:
export CCACHE_DIR=$(cygpath -u "$CCACHE_DIR") export CCACHE_DIR=$(cygpath -u "$CCACHE_DIR")
echo "CCACHE_DIR=$CCACHE_DIR" echo "CCACHE_DIR=$CCACHE_DIR"
.ci/build-windows-clang.sh .ci/build-windows-clang.sh
.ci/setup-windows-ci-vars.sh ${{ matrix.arch }} ${{ matrix.compiler }}
.ci/deploy-windows-${{ matrix.compiler }}.sh
- name: install DIA SDK - name: install DIA SDK
if: ${{ matrix.compiler == 'clang-cl' }} if: ${{ matrix.compiler == 'clang-cl' }}
@ -484,21 +483,18 @@ jobs:
- name: Build RPCS3 - name: Build RPCS3
if: ${{ matrix.compiler == 'clang-cl' }} if: ${{ matrix.compiler == 'clang-cl' }}
shell: bash shell: bash
run: .ci/build-windows-clang-cl.sh run: |
.ci/build-windows-clang-cl.sh
.ci/setup-windows-ci-vars.sh ${{ matrix.arch }} ${{ matrix.compiler }}
.ci/deploy-windows-${{ matrix.compiler }}.sh
- name: Save build Ccache - name: Save build Ccache
#if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main uses: actions/cache/save@main
with: with:
path: ${{ env.CCACHE_DIR }} path: ${{ env.CCACHE_DIR }}
key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }}
- name: Prepare Artifacts
shell: bash
run: |
.ci/setup-windows-ci-vars.sh ${{ matrix.arch }} ${{ matrix.compiler }}
.ci/deploy-windows-${{ matrix.compiler }}.sh
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@main uses: actions/upload-artifact@main
with: with:
@ -508,8 +504,8 @@ jobs:
if-no-files-found: error if-no-files-found: error
FreeBSD_Build: FreeBSD_Build:
# Only run push event on master branch of main repo, but run all PRs # Only run push event on master branch of main repo, but run all PRs
#if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master')
name: RPCS3 FreeBSD name: RPCS3 FreeBSD
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 60 timeout-minutes: 60
@ -540,7 +536,7 @@ jobs:
run: .ci/install-freebsd.sh && .ci/build-freebsd.sh run: .ci/install-freebsd.sh && .ci/build-freebsd.sh
- name: Save Build Ccache - name: Save Build Ccache
#if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main uses: actions/cache/save@main
with: with:
path: ${{ env.CCACHE_DIR }} path: ${{ env.CCACHE_DIR }}

5
3rdparty/qt6.cmake vendored
View file

@ -6,14 +6,15 @@ find_package(Qt6 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent Multimedia M
if(WIN32) if(WIN32)
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets) target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
else() else()
find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui) set(QT_NO_PRIVATE_MODULE_WARNING ON)
find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui GuiPrivate)
if(Qt6DBus_FOUND) if(Qt6DBus_FOUND)
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::DBus Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets) target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::DBus Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
target_compile_definitions(3rdparty_qt6 INTERFACE -DHAVE_QTDBUS) target_compile_definitions(3rdparty_qt6 INTERFACE -DHAVE_QTDBUS)
else() else()
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets) target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
endif() endif()
target_include_directories(3rdparty_qt6 INTERFACE ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) target_link_libraries(3rdparty_qt6 INTERFACE Qt6::GuiPrivate)
endif() endif()
if(Qt6Widgets_FOUND) if(Qt6Widgets_FOUND)

View file

@ -162,7 +162,7 @@ if (NOT ANDROID)
add_custom_command(TARGET rpcs3 POST_BUILD add_custom_command(TARGET rpcs3 POST_BUILD
COMMAND ${WINDEPLOYQT_EXECUTABLE} --no-compiler-runtime --no-opengl-sw --no-patchqt COMMAND ${WINDEPLOYQT_EXECUTABLE} --no-compiler-runtime --no-opengl-sw --no-patchqt
--no-translations --no-system-d3d-compiler --no-system-dxc-compiler --no-quick-import --no-translations --no-system-d3d-compiler --no-system-dxc-compiler --no-quick-import
--plugindir $<TARGET_FILE_DIR:rpcs3>/qt6/plugins --plugindir "$<IF:$<CXX_COMPILER_FRONTEND_VARIANT:MSVC>,$<TARGET_FILE_DIR:rpcs3>/qt6/plugins,$<TARGET_FILE_DIR:rpcs3>/share/qt6/plugins>"
--verbose 0 --verbose 0
$<TARGET_FILE:rpcs3> $<TARGET_FILE:rpcs3>
) )

View file

@ -591,6 +591,7 @@ if(TARGET 3rdparty_vulkan)
RSX/VK/vkutils/device.cpp RSX/VK/vkutils/device.cpp
RSX/VK/vkutils/sampler.cpp RSX/VK/vkutils/sampler.cpp
RSX/VK/vkutils/shared.cpp RSX/VK/vkutils/shared.cpp
RSX/VK/vkutils/unique_resource.cpp
RSX/VK/VKAsyncScheduler.cpp RSX/VK/VKAsyncScheduler.cpp
RSX/VK/VKCommandStream.cpp RSX/VK/VKCommandStream.cpp
RSX/VK/VKCommonDecompiler.cpp RSX/VK/VKCommonDecompiler.cpp

View file

@ -3198,7 +3198,7 @@ error_code sceNpLookupTerm()
error_code sceNpLookupCreateTitleCtx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpId> selfNpId) error_code sceNpLookupCreateTitleCtx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpId> selfNpId)
{ {
sceNp.warning("sceNpLookupCreateTitleCtx(communicationId=*0x%x(%s), selfNpId=0x%x)", communicationId, communicationId ? communicationId->data : "", selfNpId); sceNp.warning("sceNpLookupCreateTitleCtx(communicationId=*0x%x(%s), selfNpId=0x%x)", communicationId, communicationId ? std::string_view(communicationId->data, 9) : "", selfNpId);
auto& nph = g_fxo->get<named_thread<np::np_handler>>(); auto& nph = g_fxo->get<named_thread<np::np_handler>>();
@ -6962,7 +6962,7 @@ error_code sceNpSignalingGetConnectionFromPeerAddress(u32 ctx_id, np_in_addr_t p
return CELL_OK; return CELL_OK;
} }
error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptr<SceNpSignalingNetInfo> info) error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptr<SceNpSignalingNetInfoDeprecated> info)
{ {
sceNp.warning("sceNpSignalingGetLocalNetInfo(ctx_id=%d, info=*0x%x)", ctx_id, info); sceNp.warning("sceNpSignalingGetLocalNetInfo(ctx_id=%d, info=*0x%x)", ctx_id, info);
@ -6973,7 +6973,8 @@ error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptr<SceNpSignalingNetIn
return SCE_NP_SIGNALING_ERROR_NOT_INITIALIZED; return SCE_NP_SIGNALING_ERROR_NOT_INITIALIZED;
} }
if (!info || info->size != sizeof(SceNpSignalingNetInfo)) // Library has backward support for a version of SceNpSignalingNetInfo without npport
if (!info || (info->size != sizeof(SceNpSignalingNetInfo) && info->size != sizeof(SceNpSignalingNetInfoDeprecated)))
{ {
return SCE_NP_SIGNALING_ERROR_INVALID_ARGUMENT; return SCE_NP_SIGNALING_ERROR_INVALID_ARGUMENT;
} }
@ -6985,7 +6986,12 @@ error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptr<SceNpSignalingNetIn
info->nat_status = SCE_NP_SIGNALING_NETINFO_NAT_STATUS_TYPE2; info->nat_status = SCE_NP_SIGNALING_NETINFO_NAT_STATUS_TYPE2;
info->upnp_status = nph.get_upnp_status(); info->upnp_status = nph.get_upnp_status();
info->npport_status = SCE_NP_SIGNALING_NETINFO_NPPORT_STATUS_OPEN; info->npport_status = SCE_NP_SIGNALING_NETINFO_NPPORT_STATUS_OPEN;
info->npport = SCE_NP_PORT;
if (info->size == sizeof(SceNpSignalingNetInfo))
{
auto new_info = vm::unsafe_ptr_cast<SceNpSignalingNetInfo>(info);
new_info->npport = SCE_NP_PORT;
}
return CELL_OK; return CELL_OK;
} }

View file

@ -1584,6 +1584,16 @@ struct SceNpSignalingNetInfo
be_t<u16> npport; be_t<u16> npport;
}; };
struct SceNpSignalingNetInfoDeprecated
{
be_t<u32> size;
be_t<u32> local_addr; // in_addr
be_t<u32> mapped_addr; // in_addr
be_t<s32> nat_status;
be_t<s32> upnp_status;
be_t<s32> npport_status;
};
struct SceNpCustomMenuAction struct SceNpCustomMenuAction
{ {
be_t<u32> options; be_t<u32> options;

View file

@ -1300,7 +1300,7 @@ error_code sceNpMatching2GrantRoomOwner(
error_code sceNpMatching2CreateContext( error_code sceNpMatching2CreateContext(
vm::cptr<SceNpId> npId, vm::cptr<SceNpCommunicationId> commId, vm::cptr<SceNpCommunicationPassphrase> passPhrase, vm::ptr<SceNpMatching2ContextId> ctxId, s32 option) vm::cptr<SceNpId> npId, vm::cptr<SceNpCommunicationId> commId, vm::cptr<SceNpCommunicationPassphrase> passPhrase, vm::ptr<SceNpMatching2ContextId> ctxId, s32 option)
{ {
sceNp2.warning("sceNpMatching2CreateContext(npId=*0x%x, commId=*0x%x(%s), passPhrase=*0x%x, ctxId=*0x%x, option=%d)", npId, commId, commId ? commId->data : "", passPhrase, ctxId, option); sceNp2.warning("sceNpMatching2CreateContext(npId=*0x%x, commId=*0x%x(%s), passPhrase=*0x%x, ctxId=*0x%x, option=%d)", npId, commId, commId ? std::string_view(commId->data, 9) : "", passPhrase, ctxId, option);
auto& nph = g_fxo->get<named_thread<np::np_handler>>(); auto& nph = g_fxo->get<named_thread<np::np_handler>>();

View file

@ -4,6 +4,7 @@
#include "Emu/Cell/PPUCallback.h" #include "Emu/Cell/PPUCallback.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/Cell/Modules/cellSysutil.h" #include "Emu/Cell/Modules/cellSysutil.h"
#include "np_helpers.h"
LOG_CHANNEL(sceNp2); LOG_CHANNEL(sceNp2);
@ -53,7 +54,7 @@ void generic_async_transaction_context::set_result_and_wake(error_code err)
tus_ctx::tus_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase) tus_ctx::tus_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{ {
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9); ensure(communicationId && np::validate_communication_id(*communicationId), "tus_ctx::tus_ctx: Invalid SceNpCommunicationId");
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId)); memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase)); memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
} }
@ -96,7 +97,7 @@ bool destroy_tus_transaction_context(s32 ctx_id)
score_ctx::score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase) score_ctx::score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{ {
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9); ensure(communicationId && np::validate_communication_id(*communicationId), "score_ctx::score_ctx: Invalid SceNpCommunicationId");
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId)); memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase)); memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
} }
@ -140,7 +141,7 @@ bool destroy_score_transaction_context(s32 ctx_id)
match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option) match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option)
{ {
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9); ensure(communicationId && np::validate_communication_id(*communicationId), "match2_ctx::match2_ctx: Invalid SceNpCommunicationId");
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId)); memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase)); memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
@ -149,7 +150,7 @@ match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<
} }
u16 create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option) u16 create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option)
{ {
sceNp2.notice("Creating match2 context with communicationId: <%s>", static_cast<const char*>(communicationId->data)); sceNp2.notice("Creating match2 context with communicationId: <%s>", std::string_view(communicationId->data, 9));
return static_cast<u16>(idm::make<match2_ctx>(communicationId, passphrase, option)); return static_cast<u16>(idm::make<match2_ctx>(communicationId, passphrase, option));
} }
bool destroy_match2_context(u16 ctx_id) bool destroy_match2_context(u16 ctx_id)
@ -167,7 +168,7 @@ shared_ptr<match2_ctx> get_match2_context(u16 ctx_id)
lookup_title_ctx::lookup_title_ctx(vm::cptr<SceNpCommunicationId> communicationId) lookup_title_ctx::lookup_title_ctx(vm::cptr<SceNpCommunicationId> communicationId)
{ {
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9); ensure(communicationId && np::validate_communication_id(*communicationId), "lookup_title_ctx::lookup_title_ctx: Invalid SceNpCommunicationId");
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId)); memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
} }
s32 create_lookup_title_context(vm::cptr<SceNpCommunicationId> communicationId) s32 create_lookup_title_context(vm::cptr<SceNpCommunicationId> communicationId)

View file

@ -1,3 +1,4 @@
#include "Emu/Cell/Modules/sceNp.h"
#include "stdafx.h" #include "stdafx.h"
#include "util/types.hpp" #include "util/types.hpp"
#include "Utilities/StrUtil.h" #include "Utilities/StrUtil.h"
@ -22,9 +23,15 @@ namespace np
return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]); return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
} }
bool validate_communication_id(const SceNpCommunicationId& com_id)
{
return std::all_of(com_id.data, com_id.data + 9, [](char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'); }) && com_id.num <= 99;
}
std::string communication_id_to_string(const SceNpCommunicationId& communicationId) std::string communication_id_to_string(const SceNpCommunicationId& communicationId)
{ {
return fmt::format("%s_%02d", communicationId.data, communicationId.num); std::string_view com_id_data(communicationId.data, 9);
return fmt::format("%s_%02d", com_id_data, communicationId.num);
} }
void strings_to_userinfo(std::string_view npid, std::string_view online_name, std::string_view avatar_url, SceNpUserInfo& user_info) void strings_to_userinfo(std::string_view npid, std::string_view online_name, std::string_view avatar_url, SceNpUserInfo& user_info)

View file

@ -8,6 +8,7 @@ namespace np
{ {
std::string ip_to_string(u32 addr); std::string ip_to_string(u32 addr);
std::string ether_to_string(std::array<u8, 6>& ether); std::string ether_to_string(std::array<u8, 6>& ether);
bool validate_communication_id(const SceNpCommunicationId& com_id);
std::string communication_id_to_string(const SceNpCommunicationId& communicationId); std::string communication_id_to_string(const SceNpCommunicationId& communicationId);
void string_to_npid(std::string_view str, SceNpId& npid); void string_to_npid(std::string_view str, SceNpId& npid);

View file

@ -2752,7 +2752,7 @@ namespace rpcn
void rpcn_client::write_communication_id(const SceNpCommunicationId& com_id, std::vector<u8>& data) void rpcn_client::write_communication_id(const SceNpCommunicationId& com_id, std::vector<u8>& data)
{ {
ensure(com_id.data[9] == 0 && com_id.num <= 99, "rpcn_client::write_communication_id: Invalid SceNpCommunicationId"); ensure(np::validate_communication_id(com_id), "rpcn_client::write_communication_id: Invalid SceNpCommunicationId");
const std::string com_id_str = np::communication_id_to_string(com_id); const std::string com_id_str = np::communication_id_to_string(com_id);
ensure(com_id_str.size() == 12, "rpcn_client::write_communication_id: Error formatting SceNpCommunicationId"); ensure(com_id_str.size() == 12, "rpcn_client::write_communication_id: Error formatting SceNpCommunicationId");
memcpy(data.data(), com_id_str.data(), COMMUNICATION_ID_SIZE); memcpy(data.data(), com_id_str.data(), COMMUNICATION_ID_SIZE);

View file

@ -246,7 +246,7 @@ namespace vk
void cs_shuffle_base::bind_resources(const vk::command_buffer& cmd) void cs_shuffle_base::bind_resources(const vk::command_buffer& cmd)
{ {
set_parameters(cmd); set_parameters(cmd);
m_program->bind_uniform({ m_data->value, m_data_offset, m_data_length }, 0, 0); m_program->bind_uniform({ *m_data, m_data_offset, m_data_length }, 0, 0);
} }
void cs_shuffle_base::set_parameters(const vk::command_buffer& cmd) void cs_shuffle_base::set_parameters(const vk::command_buffer& cmd)
@ -296,7 +296,7 @@ namespace vk
void cs_interleave_task::bind_resources(const vk::command_buffer& cmd) void cs_interleave_task::bind_resources(const vk::command_buffer& cmd)
{ {
set_parameters(cmd); set_parameters(cmd);
m_program->bind_uniform({ m_data->value, m_data_offset, m_ssbo_length }, 0, 0); m_program->bind_uniform({ *m_data, m_data_offset, m_ssbo_length }, 0, 0);
} }
void cs_interleave_task::run(const vk::command_buffer& cmd, const vk::buffer* data, u32 data_offset, u32 data_length, u32 zeta_offset, u32 stencil_offset) void cs_interleave_task::run(const vk::command_buffer& cmd, const vk::buffer* data, u32 data_offset, u32 data_length, u32 zeta_offset, u32 stencil_offset)
@ -355,8 +355,8 @@ namespace vk
void cs_aggregator::bind_resources(const vk::command_buffer& /*cmd*/) void cs_aggregator::bind_resources(const vk::command_buffer& /*cmd*/)
{ {
m_program->bind_uniform({ src->value, 0, block_length }, 0, 0); m_program->bind_uniform({ *src, 0, block_length }, 0, 0);
m_program->bind_uniform({ dst->value, 0, 4 }, 0, 1); m_program->bind_uniform({ *dst, 0, 4 }, 0, 1);
} }
void cs_aggregator::run(const vk::command_buffer& cmd, const vk::buffer* dst, const vk::buffer* src, u32 num_words) void cs_aggregator::run(const vk::command_buffer& cmd, const vk::buffer* dst, const vk::buffer* src, u32 num_words)

View file

@ -347,7 +347,7 @@ namespace vk
void bind_resources(const vk::command_buffer& cmd) override void bind_resources(const vk::command_buffer& cmd) override
{ {
set_parameters(cmd); set_parameters(cmd);
m_program->bind_uniform({ m_data->value, m_data_offset, m_ssbo_length }, 0, 0); m_program->bind_uniform({ *m_data, m_data_offset, m_ssbo_length }, 0, 0);
} }
void run(const vk::command_buffer& cmd, const vk::buffer* data, u32 src_offset, u32 src_length, u32 dst_offset) void run(const vk::command_buffer& cmd, const vk::buffer* data, u32 src_offset, u32 src_length, u32 dst_offset)
@ -449,8 +449,8 @@ namespace vk
{ {
set_parameters(cmd); set_parameters(cmd);
m_program->bind_uniform({ src_buffer->value, in_offset, block_length }, 0, 0); m_program->bind_uniform({ *src_buffer, in_offset, block_length }, 0, 0);
m_program->bind_uniform({ dst_buffer->value, out_offset, block_length }, 0, 1); m_program->bind_uniform({ *dst_buffer, out_offset, block_length }, 0, 1);
} }
void set_parameters(const vk::command_buffer& cmd) void set_parameters(const vk::command_buffer& cmd)
@ -579,8 +579,8 @@ namespace vk
set_parameters(cmd); set_parameters(cmd);
const auto op = static_cast<u32>(Op); const auto op = static_cast<u32>(Op);
m_program->bind_uniform({ src_buffer->value, in_offset, in_block_length }, 0u, 0u ^ op); m_program->bind_uniform({ *src_buffer, in_offset, in_block_length }, 0u, 0u ^ op);
m_program->bind_uniform({ dst_buffer->value, out_offset, out_block_length }, 0u, 1u ^ op); m_program->bind_uniform({ *dst_buffer, out_offset, out_block_length }, 0u, 1u ^ op);
} }
void set_parameters(const vk::command_buffer& cmd) void set_parameters(const vk::command_buffer& cmd)

View file

@ -505,16 +505,17 @@ void VKGSRender::load_texture_env()
} }
} }
if (g_cfg.video.vk.asynchronous_texture_streaming) if (backend_config.supports_asynchronous_compute)
{ {
// We have to do this here, because we have to assume the CB will be dumped // We have to do this here, because we have to assume the CB will be dumped
auto& async_task_scheduler = g_fxo->get<vk::AsyncTaskScheduler>(); auto async_task_scheduler = g_fxo->try_get<vk::AsyncTaskScheduler>();
if (async_task_scheduler.is_recording() && if (async_task_scheduler &&
!async_task_scheduler.is_host_mode()) async_task_scheduler->is_recording() &&
!async_task_scheduler->is_host_mode())
{ {
// Sync any async scheduler tasks // Sync any async scheduler tasks
if (auto ev = async_task_scheduler.get_primary_sync_label()) if (auto ev = async_task_scheduler->get_primary_sync_label())
{ {
ev->gpu_wait(*m_current_command_buffer, m_async_compute_dependency_info); ev->gpu_wait(*m_current_command_buffer, m_async_compute_dependency_info);
} }
@ -816,8 +817,8 @@ void VKGSRender::emit_geometry(u32 sub_index)
m_current_command_buffer->flags |= (vk::command_buffer::cb_has_occlusion_task | vk::command_buffer::cb_has_open_query); m_current_command_buffer->flags |= (vk::command_buffer::cb_has_occlusion_task | vk::command_buffer::cb_has_open_query);
} }
auto persistent_buffer = m_persistent_attribute_storage ? m_persistent_attribute_storage->value : null_buffer_view->value; VkDescriptorBufferViewEx persistent_buffer = m_persistent_attribute_storage ? *m_persistent_attribute_storage : *null_buffer_view;
auto volatile_buffer = m_volatile_attribute_storage ? m_volatile_attribute_storage->value : null_buffer_view->value; VkDescriptorBufferViewEx volatile_buffer = m_volatile_attribute_storage ? *m_volatile_attribute_storage : *null_buffer_view;
bool update_descriptors = false; bool update_descriptors = false;
if (m_current_draw.subdraw_id == 0) if (m_current_draw.subdraw_id == 0)

View file

@ -553,13 +553,13 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar)
} }
// Initialize optional allocation information with placeholders // Initialize optional allocation information with placeholders
m_vertex_env_buffer_info = { m_vertex_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_vertex_env_buffer_info = { *m_vertex_env_ring_info.heap, 0, VK_WHOLE_SIZE };
m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_vertex_constants_buffer_info = { *m_transform_constants_ring_info.heap, 0, VK_WHOLE_SIZE };
m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_fragment_env_buffer_info = { *m_fragment_env_ring_info.heap, 0, VK_WHOLE_SIZE };
m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_fragment_texture_params_buffer_info = { *m_fragment_texture_params_ring_info.heap, 0, VK_WHOLE_SIZE };
m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_raster_env_buffer_info = { *m_raster_env_ring_info.heap, 0, VK_WHOLE_SIZE };
m_vertex_layout_stream_info = { m_vertex_layout_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_vertex_layout_stream_info = { *m_vertex_layout_ring_info.heap, 0, VK_WHOLE_SIZE };
m_fragment_constants_buffer_info = { m_fragment_constants_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_fragment_constants_buffer_info = { *m_fragment_constants_ring_info.heap, 0, VK_WHOLE_SIZE };
const auto& limits = m_device->gpu().get_limits(); const auto& limits = m_device->gpu().get_limits();
m_texbuffer_view_size = std::min(limits.maxTexelBufferElements, VK_ATTRIB_RING_BUFFER_SIZE_M * 0x100000u); m_texbuffer_view_size = std::min(limits.maxTexelBufferElements, VK_ATTRIB_RING_BUFFER_SIZE_M * 0x100000u);
@ -1980,8 +1980,8 @@ void VKGSRender::load_program_env()
m_draw_processor.fill_constants_instancing_buffer(indirection_table_buf, constants_array_buf, bound_vertex_prog); m_draw_processor.fill_constants_instancing_buffer(indirection_table_buf, constants_array_buf, bound_vertex_prog);
m_instancing_buffer_ring_info.unmap(); m_instancing_buffer_ring_info.unmap();
m_instancing_indirection_buffer_info = { m_instancing_buffer_ring_info.heap->value, indirection_table_offset, indirection_table_buf.size() }; m_instancing_indirection_buffer_info = { *m_instancing_buffer_ring_info.heap, indirection_table_offset, indirection_table_buf.size() };
m_instancing_constants_array_buffer_info = { m_instancing_buffer_ring_info.heap->value, constants_data_table_offset, constants_array_buf.size() }; m_instancing_constants_array_buffer_info = { *m_instancing_buffer_ring_info.heap, constants_data_table_offset, constants_array_buf.size() };
} }
else if (update_transform_constants) else if (update_transform_constants)
{ {
@ -2066,7 +2066,7 @@ void VKGSRender::load_program_env()
std::memcpy(vp_buf + 16, current_vertex_program.data.data(), current_vp_metadata.ucode_length); std::memcpy(vp_buf + 16, current_vertex_program.data.data(), current_vp_metadata.ucode_length);
m_vertex_instructions_buffer.unmap(); m_vertex_instructions_buffer.unmap();
m_vertex_instructions_buffer_info = { m_vertex_instructions_buffer.heap->value, vp_mapping, vp_block_length }; m_vertex_instructions_buffer_info = { *m_vertex_instructions_buffer.heap, vp_mapping, vp_block_length };
} }
if (m_interpreter_state & rsx::fragment_program_dirty) if (m_interpreter_state & rsx::fragment_program_dirty)
@ -2084,7 +2084,7 @@ void VKGSRender::load_program_env()
std::memcpy(fp_buf + 16, current_fragment_program.get_data(), current_fragment_program.ucode_length); std::memcpy(fp_buf + 16, current_fragment_program.get_data(), current_fragment_program.ucode_length);
m_fragment_instructions_buffer.unmap(); m_fragment_instructions_buffer.unmap();
m_fragment_instructions_buffer_info = { m_fragment_instructions_buffer.heap->value, fp_mapping, fp_block_length }; m_fragment_instructions_buffer_info = { *m_fragment_instructions_buffer.heap, fp_mapping, fp_block_length };
} }
} }
@ -2111,7 +2111,7 @@ void VKGSRender::load_program_env()
if (vk::emulate_conditional_rendering()) if (vk::emulate_conditional_rendering())
{ {
const VkBuffer predicate = m_cond_render_buffer ? m_cond_render_buffer->value : vk::get_scratch_buffer(*m_current_command_buffer, 4)->value; const vk::buffer& predicate = m_cond_render_buffer ? *m_cond_render_buffer : *vk::get_scratch_buffer(*m_current_command_buffer, 4);
const u32 offset = cond_render_ctrl.hw_cond_active ? 0 : 4; const u32 offset = cond_render_ctrl.hw_cond_active ? 0 : 4;
m_program->bind_uniform({ predicate, offset, 4 }, vk::glsl::binding_set_index_vertex, m_vs_binding_table->cr_pred_buffer_location); m_program->bind_uniform({ predicate, offset, 4 }, vk::glsl::binding_set_index_vertex, m_vs_binding_table->cr_pred_buffer_location);
} }

View file

@ -4,6 +4,7 @@
#include "vkutils/descriptors.h" #include "vkutils/descriptors.h"
#include "vkutils/data_heap.h" #include "vkutils/data_heap.h"
#include "vkutils/ex.h"
#include "vkutils/instance.h" #include "vkutils/instance.h"
#include "vkutils/sync.h" #include "vkutils/sync.h"
#include "vkutils/swapchain.h" #include "vkutils/swapchain.h"
@ -136,18 +137,18 @@ private:
vk::data_heap m_fragment_instructions_buffer; vk::data_heap m_fragment_instructions_buffer;
vk::data_heap m_vertex_instructions_buffer; vk::data_heap m_vertex_instructions_buffer;
VkDescriptorBufferInfo m_vertex_env_buffer_info {}; VkDescriptorBufferInfoEx m_vertex_env_buffer_info {};
VkDescriptorBufferInfo m_fragment_env_buffer_info {}; VkDescriptorBufferInfoEx m_fragment_env_buffer_info {};
VkDescriptorBufferInfo m_vertex_layout_stream_info {}; VkDescriptorBufferInfoEx m_vertex_layout_stream_info {};
VkDescriptorBufferInfo m_vertex_constants_buffer_info {}; VkDescriptorBufferInfoEx m_vertex_constants_buffer_info {};
VkDescriptorBufferInfo m_fragment_constants_buffer_info {}; VkDescriptorBufferInfoEx m_fragment_constants_buffer_info {};
VkDescriptorBufferInfo m_fragment_texture_params_buffer_info {}; VkDescriptorBufferInfoEx m_fragment_texture_params_buffer_info {};
VkDescriptorBufferInfo m_raster_env_buffer_info {}; VkDescriptorBufferInfoEx m_raster_env_buffer_info {};
VkDescriptorBufferInfo m_instancing_indirection_buffer_info {}; VkDescriptorBufferInfoEx m_instancing_indirection_buffer_info {};
VkDescriptorBufferInfo m_instancing_constants_array_buffer_info{}; VkDescriptorBufferInfoEx m_instancing_constants_array_buffer_info{};
VkDescriptorBufferInfo m_vertex_instructions_buffer_info {}; VkDescriptorBufferInfoEx m_vertex_instructions_buffer_info {};
VkDescriptorBufferInfo m_fragment_instructions_buffer_info {}; VkDescriptorBufferInfoEx m_fragment_instructions_buffer_info {};
rsx::simple_array<u8> m_multidraw_parameters_buffer; rsx::simple_array<u8> m_multidraw_parameters_buffer;
u64 m_xform_constants_dynamic_offset = 0; // We manage transform_constants dynamic offset manually to alleviate performance penalty of doing a hot-patch of constants. u64 m_xform_constants_dynamic_offset = 0; // We manage transform_constants dynamic offset manually to alleviate performance penalty of doing a hot-patch of constants.

View file

@ -183,7 +183,7 @@ namespace vk
if (m_num_uniform_buffers > 0) if (m_num_uniform_buffers > 0)
{ {
program->bind_uniform({ m_ubo.heap->value, m_ubo_offset, std::max(m_ubo_length, 4u) }, 0, 0); program->bind_uniform({ *m_ubo.heap, m_ubo_offset, std::max(m_ubo_length, 4u) }, 0, 0);
} }
for (uint n = 0; n < src.size(); ++n) for (uint n = 0; n < src.size(); ++n)

View file

@ -18,25 +18,26 @@ namespace vk
{ {
const auto ptr = std::get_if<VkDescriptorImageInfoEx>(&a); const auto ptr = std::get_if<VkDescriptorImageInfoEx>(&a);
return !!ptr && return !!ptr &&
ptr->imageView == b.imageView &&
ptr->resourceId == b.resourceId && ptr->resourceId == b.resourceId &&
ptr->imageView == b.imageView &&
ptr->sampler == b.sampler && ptr->sampler == b.sampler &&
ptr->imageLayout == b.imageLayout; ptr->imageLayout == b.imageLayout;
} }
bool operator == (const descriptor_slot_t& a, const VkDescriptorBufferInfo& b) bool operator == (const descriptor_slot_t& a, const VkDescriptorBufferInfoEx& b)
{ {
const auto ptr = std::get_if<VkDescriptorBufferInfo>(&a); const auto ptr = std::get_if<VkDescriptorBufferInfoEx>(&a);
return !!ptr && return !!ptr &&
ptr->resourceId == b.resourceId &&
ptr->buffer == b.buffer && ptr->buffer == b.buffer &&
ptr->offset == b.offset && ptr->offset == b.offset &&
ptr->range == b.range; ptr->range == b.range;
} }
bool operator == (const descriptor_slot_t& a, const VkBufferView& b) bool operator == (const descriptor_slot_t& a, const VkDescriptorBufferViewEx& b)
{ {
const auto ptr = std::get_if<VkBufferView>(&a); const auto ptr = std::get_if<VkDescriptorBufferViewEx>(&a);
return !!ptr && *ptr == b; return !!ptr && ptr->resourceId == b.resourceId;
} }
bool operator == (const descriptor_slot_t& a, const std::span<const VkDescriptorImageInfoEx>& b) bool operator == (const descriptor_slot_t& a, const std::span<const VkDescriptorImageInfoEx>& b)
@ -324,7 +325,7 @@ namespace vk
m_sets[set_id].notify_descriptor_slot_updated(binding_point, image_descriptor); m_sets[set_id].notify_descriptor_slot_updated(binding_point, image_descriptor);
} }
void program::bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, u32 set_id, u32 binding_point) void program::bind_uniform(const VkDescriptorBufferInfoEx &buffer_descriptor, u32 set_id, u32 binding_point)
{ {
if (m_sets[set_id].m_descriptor_slots[binding_point] == buffer_descriptor) if (m_sets[set_id].m_descriptor_slots[binding_point] == buffer_descriptor)
{ {
@ -334,7 +335,7 @@ namespace vk
m_sets[set_id].notify_descriptor_slot_updated(binding_point, buffer_descriptor); m_sets[set_id].notify_descriptor_slot_updated(binding_point, buffer_descriptor);
} }
void program::bind_uniform(const VkBufferView &buffer_view, u32 set_id, u32 binding_point) void program::bind_uniform(const VkDescriptorBufferViewEx& buffer_view, u32 set_id, u32 binding_point)
{ {
if (m_sets[set_id].m_descriptor_slots[binding_point] == buffer_view) if (m_sets[set_id].m_descriptor_slots[binding_point] == buffer_view)
{ {
@ -486,15 +487,15 @@ namespace vk
return; return;
} }
if (auto ptr = std::get_if<VkDescriptorBufferInfo>(&slot)) if (auto ptr = std::get_if<VkDescriptorBufferInfoEx>(&slot))
{ {
m_descriptor_set.push(*ptr, type, idx); m_descriptor_set.push(*ptr, type, idx);
return; return;
} }
if (auto ptr = std::get_if<VkBufferView>(&slot)) if (auto ptr = std::get_if<VkDescriptorBufferViewEx>(&slot))
{ {
m_descriptor_set.push(*ptr, type, idx); m_descriptor_set.push(ptr->view, type, idx);
return; return;
} }
@ -537,15 +538,15 @@ namespace vk
return; return;
} }
if (auto ptr = std::get_if<VkDescriptorBufferInfo>(&slot)) if (auto ptr = std::get_if<VkDescriptorBufferInfoEx>(&slot))
{ {
m_descriptor_template[idx].pBufferInfo = m_descriptor_set.store(*ptr); m_descriptor_template[idx].pBufferInfo = m_descriptor_set.store(*ptr);
return; return;
} }
if (auto ptr = std::get_if<VkBufferView>(&slot)) if (auto ptr = std::get_if<VkDescriptorBufferViewEx>(&slot))
{ {
m_descriptor_template[idx].pTexelBufferView = m_descriptor_set.store(*ptr); m_descriptor_template[idx].pTexelBufferView = m_descriptor_set.store(ptr->view);
return; return;
} }

View file

@ -115,7 +115,11 @@ namespace vk
}; };
using descriptor_image_array_t = rsx::simple_array<VkDescriptorImageInfoEx>; using descriptor_image_array_t = rsx::simple_array<VkDescriptorImageInfoEx>;
using descriptor_slot_t = std::variant<VkDescriptorImageInfoEx, VkDescriptorBufferInfo, VkBufferView, descriptor_image_array_t>; using descriptor_slot_t = std::variant<
VkDescriptorImageInfoEx,
VkDescriptorBufferInfoEx,
VkDescriptorBufferViewEx,
descriptor_image_array_t>;
struct descriptor_table_t struct descriptor_table_t
{ {
@ -202,9 +206,9 @@ namespace vk
std::pair<u32, u32> get_uniform_location(::glsl::program_domain domain, program_input_type type, const std::string& uniform_name); std::pair<u32, u32> get_uniform_location(::glsl::program_domain domain, program_input_type type, const std::string& uniform_name);
void bind_uniform(const VkDescriptorImageInfoEx& image_descriptor, u32 set_id, u32 binding_point); void bind_uniform(const VkDescriptorImageInfoEx& image_descriptor, u32 set_id, u32 binding_point);
void bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, u32 set_id, u32 binding_point); void bind_uniform(const VkDescriptorBufferInfoEx& buffer_descriptor, u32 set_id, u32 binding_point);
void bind_uniform(const VkBufferView &buffer_view, u32 set_id, u32 binding_point); void bind_uniform(const VkDescriptorBufferViewEx& buffer_view, u32 set_id, u32 binding_point);
void bind_uniform(const VkBufferView &buffer_view, ::glsl::program_domain domain, program_input_type type, const std::string &binding_name); void bind_uniform(const VkDescriptorBufferViewEx& buffer_view, ::glsl::program_domain domain, program_input_type type, const std::string &binding_name);
void bind_uniform_array(const std::span<const VkDescriptorImageInfoEx>& image_descriptors,u32 set_id, u32 binding_point); void bind_uniform_array(const std::span<const VkDescriptorImageInfoEx>& image_descriptors,u32 set_id, u32 binding_point);

View file

@ -867,7 +867,7 @@ namespace vk
static const vk::command_buffer& prepare_for_transfer(const vk::command_buffer& primary_cb, vk::image* dst_image, rsx::flags32_t& flags) static const vk::command_buffer& prepare_for_transfer(const vk::command_buffer& primary_cb, vk::image* dst_image, rsx::flags32_t& flags)
{ {
AsyncTaskScheduler* async_scheduler = (flags & image_upload_options::upload_contents_async) AsyncTaskScheduler* async_scheduler = (flags & image_upload_options::upload_contents_async)
? std::addressof(g_fxo->get<AsyncTaskScheduler>()) ? g_fxo->try_get<AsyncTaskScheduler>()
: nullptr; : nullptr;
if (async_scheduler && (dst_image->aspect() & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) if (async_scheduler && (dst_image->aspect() & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))

View file

@ -1115,7 +1115,7 @@ namespace vk
const bool upload_async = rsx::get_current_renderer()->get_backend_config().supports_asynchronous_compute; const bool upload_async = rsx::get_current_renderer()->get_backend_config().supports_asynchronous_compute;
rsx::flags32_t create_flags = 0; rsx::flags32_t create_flags = 0;
if (upload_async && g_fxo->get<AsyncTaskScheduler>().is_host_mode()) if (upload_async && ensure(g_fxo->try_get<AsyncTaskScheduler>())->is_host_mode())
{ {
create_flags |= texture_create_flags::do_not_reuse; create_flags |= texture_create_flags::do_not_reuse;
if (m_device->get_graphics_queue() != m_device->get_transfer_queue()) if (m_device->get_graphics_queue() != m_device->get_transfer_queue())

View file

@ -329,13 +329,13 @@ vk::vertex_upload_info VKGSRender::upload_vertex_data()
vk::get_resource_manager()->dispose(m_volatile_attribute_storage); vk::get_resource_manager()->dispose(m_volatile_attribute_storage);
} }
m_vertex_env_buffer_info = { m_vertex_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_vertex_env_buffer_info = { *m_vertex_env_ring_info.heap, 0, VK_WHOLE_SIZE };
m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_vertex_constants_buffer_info = { *m_transform_constants_ring_info.heap, 0, VK_WHOLE_SIZE };
m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_fragment_env_buffer_info = { *m_fragment_env_ring_info.heap, 0, VK_WHOLE_SIZE };
m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_fragment_texture_params_buffer_info = { *m_fragment_texture_params_ring_info.heap, 0, VK_WHOLE_SIZE };
m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_raster_env_buffer_info = { *m_raster_env_ring_info.heap, 0, VK_WHOLE_SIZE };
m_vertex_layout_stream_info = { m_vertex_layout_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_vertex_layout_stream_info = { *m_vertex_layout_ring_info.heap, 0, VK_WHOLE_SIZE };
m_fragment_constants_buffer_info = { m_fragment_constants_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_fragment_constants_buffer_info = { *m_fragment_constants_ring_info.heap, 0, VK_WHOLE_SIZE };
vk::clear_status_interrupt(vk::heap_changed); vk::clear_status_interrupt(vk::heap_changed);
} }

View file

@ -3,10 +3,11 @@
#include "../VulkanAPI.h" #include "../VulkanAPI.h"
#include "device.h" #include "device.h"
#include "memory.h" #include "memory.h"
#include "unique_resource.h"
namespace vk namespace vk
{ {
struct buffer_view struct buffer_view : public unique_resource
{ {
VkBufferView value; VkBufferView value;
VkBufferViewCreateInfo info = {}; VkBufferViewCreateInfo info = {};
@ -23,7 +24,7 @@ namespace vk
VkDevice m_device; VkDevice m_device;
}; };
struct buffer struct buffer : public unique_resource
{ {
VkBuffer value; VkBuffer value;
VkBufferCreateInfo info = {}; VkBufferCreateInfo info = {};

View file

@ -1,4 +1,5 @@
#include "ex.h" #include "ex.h"
#include "buffer_object.h"
#include "image.h" #include "image.h"
#include "sampler.h" #include "sampler.h"
@ -6,21 +7,31 @@ namespace vk
{ {
VkDescriptorImageInfoEx::VkDescriptorImageInfoEx(const vk::image_view& view, const vk::sampler& sampler, VkImageLayout layout) VkDescriptorImageInfoEx::VkDescriptorImageInfoEx(const vk::image_view& view, const vk::sampler& sampler, VkImageLayout layout)
: VkDescriptorImageInfo(sampler.value, view.value, layout) : VkDescriptorImageInfo(sampler.value, view.value, layout)
, resourceId(view.image()->id()) , resourceId(view.image()->uid())
{} {}
VkDescriptorImageInfoEx::VkDescriptorImageInfoEx(const vk::image_view& view, const vk::sampler& sampler) VkDescriptorImageInfoEx::VkDescriptorImageInfoEx(const vk::image_view& view, const vk::sampler& sampler)
: VkDescriptorImageInfo(sampler.value, view.value, view.image()->current_layout) : VkDescriptorImageInfo(sampler.value, view.value, view.image()->current_layout)
, resourceId(view.image()->id()) , resourceId(view.image()->uid())
{} {}
VkDescriptorImageInfoEx::VkDescriptorImageInfoEx(const vk::image_view& view, VkSampler sampler) VkDescriptorImageInfoEx::VkDescriptorImageInfoEx(const vk::image_view& view, VkSampler sampler)
: VkDescriptorImageInfo(sampler, view.value, view.image()->current_layout) : VkDescriptorImageInfo(sampler, view.value, view.image()->current_layout)
, resourceId(view.image()->id()) , resourceId(view.image()->uid())
{} {}
VkDescriptorImageInfoEx::VkDescriptorImageInfoEx(const vk::image_view& view) VkDescriptorImageInfoEx::VkDescriptorImageInfoEx(const vk::image_view& view)
: VkDescriptorImageInfo(VK_NULL_HANDLE, view.value, view.image()->current_layout) : VkDescriptorImageInfo(VK_NULL_HANDLE, view.value, view.image()->current_layout)
, resourceId(view.image()->id()) , resourceId(view.image()->uid())
{}
VkDescriptorBufferViewEx::VkDescriptorBufferViewEx(const vk::buffer_view& view)
: resourceId(view.uid())
, view(view.value)
{}
VkDescriptorBufferInfoEx::VkDescriptorBufferInfoEx(const vk::buffer& buffer, u64 offset, u64 range)
: VkDescriptorBufferInfo(buffer.value, offset, range)
, resourceId(buffer.uid())
{} {}
} }

View file

@ -5,6 +5,8 @@
// Custom extensions to vulkan core // Custom extensions to vulkan core
namespace vk namespace vk
{ {
struct buffer;
struct buffer_view;
struct image_view; struct image_view;
struct sampler; struct sampler;
@ -20,8 +22,27 @@ namespace vk
VkDescriptorImageInfoEx(const vk::image_view& view, VkSampler sampler); VkDescriptorImageInfoEx(const vk::image_view& view, VkSampler sampler);
VkDescriptorImageInfoEx(const vk::image_view& view); VkDescriptorImageInfoEx(const vk::image_view& view);
}; };
struct VkDescriptorBufferViewEx
{
u64 resourceId = 0ull;
VkBufferView view = VK_NULL_HANDLE;
VkDescriptorBufferViewEx() = default;
VkDescriptorBufferViewEx(const vk::buffer_view& view);
};
struct VkDescriptorBufferInfoEx : public VkDescriptorBufferInfo
{
u64 resourceId = 0ull;
VkDescriptorBufferInfoEx() = default;
VkDescriptorBufferInfoEx(const vk::buffer& buffer, u64 offset, u64 range);
};
} }
// Re-export // Re-export
using VkDescriptorImageInfoEx = vk::VkDescriptorImageInfoEx; using VkDescriptorImageInfoEx = vk::VkDescriptorImageInfoEx;
using VkDescriptorBufferViewEx = vk::VkDescriptorBufferViewEx;
using VkDescriptorBufferInfoEx = vk::VkDescriptorBufferInfoEx;

View file

@ -10,8 +10,6 @@
namespace vk namespace vk
{ {
static atomic_t<u64> s_image_uid_counter = 0;
void image::validate(const vk::render_device& dev, const VkImageCreateInfo& info) const void image::validate(const vk::render_device& dev, const VkImageCreateInfo& info) const
{ {
const auto& gpu_limits = dev.gpu().get_limits(); const auto& gpu_limits = dev.gpu().get_limits();
@ -121,8 +119,6 @@ namespace vk
CHECK_RESULT(vkCreateImage(m_device, &info, nullptr, &value)); CHECK_RESULT(vkCreateImage(m_device, &info, nullptr, &value));
m_uid = s_image_uid_counter++;
VkMemoryRequirements memory_req; VkMemoryRequirements memory_req;
vkGetImageMemoryRequirements(m_device, value, &memory_req); vkGetImageMemoryRequirements(m_device, value, &memory_req);

View file

@ -6,6 +6,7 @@
#include "commands.h" #include "commands.h"
#include "device.h" #include "device.h"
#include "memory.h" #include "memory.h"
#include "unique_resource.h"
#include <stack> #include <stack>
@ -26,7 +27,7 @@ namespace vk
VK_IMAGE_CREATE_SPECIAL_FLAGS_RPCS3 = (VK_IMAGE_CREATE_ALLOW_NULL_RPCS3 | VK_IMAGE_CREATE_SHAREABLE_RPCS3) VK_IMAGE_CREATE_SPECIAL_FLAGS_RPCS3 = (VK_IMAGE_CREATE_ALLOW_NULL_RPCS3 | VK_IMAGE_CREATE_SHAREABLE_RPCS3)
}; };
class image class image : public unique_resource
{ {
std::stack<VkImageLayout> m_layout_stack; std::stack<VkImageLayout> m_layout_stack;
VkImageAspectFlags m_storage_aspect = 0; VkImageAspectFlags m_storage_aspect = 0;
@ -68,7 +69,6 @@ namespace vk
image(image&&) = delete; image(image&&) = delete;
// Identifiers // Identifiers
u64 id() const { return m_uid; }
VkImage handle() const { return value; } VkImage handle() const { return value; }
// Properties // Properties
@ -99,7 +99,6 @@ namespace vk
protected: protected:
VkDevice m_device = VK_NULL_HANDLE; VkDevice m_device = VK_NULL_HANDLE;
u64 m_uid = 0ull;
}; };
struct image_view struct image_view

View file

@ -0,0 +1,12 @@
#include "unique_resource.h"
#include <util/atomic.hpp>
namespace vk
{
static atomic_t<u64> s_resource_uid;
u64 gen_uid()
{
return s_resource_uid++;
}
}

View file

@ -0,0 +1,22 @@
#pragma once
#include <util/types.hpp>
namespace vk
{
u64 gen_uid();
class unique_resource
{
public:
unique_resource()
: m_uid(gen_uid())
{}
u64 uid() const { return m_uid; }
bool operator == (const unique_resource& other) const { return m_uid == other.m_uid; }
private:
u64 m_uid = 0ull;
};
}

View file

@ -67,6 +67,7 @@
<ClInclude Include="Emu\RSX\VK\vkutils\sampler.h" /> <ClInclude Include="Emu\RSX\VK\vkutils\sampler.h" />
<ClInclude Include="Emu\RSX\VK\vkutils\shared.h" /> <ClInclude Include="Emu\RSX\VK\vkutils\shared.h" />
<ClInclude Include="Emu\RSX\VK\vkutils\instance.h" /> <ClInclude Include="Emu\RSX\VK\vkutils\instance.h" />
<ClInclude Include="Emu\RSX\VK\vkutils\unique_resource.h" />
<ClInclude Include="Emu\RSX\VK\VKVertexProgram.h" /> <ClInclude Include="Emu\RSX\VK\VKVertexProgram.h" />
<ClInclude Include="Emu\RSX\VK\VulkanAPI.h" /> <ClInclude Include="Emu\RSX\VK\VulkanAPI.h" />
</ItemGroup> </ItemGroup>
@ -113,6 +114,7 @@
<ClCompile Include="Emu\RSX\VK\vkutils\device.cpp" /> <ClCompile Include="Emu\RSX\VK\vkutils\device.cpp" />
<ClCompile Include="Emu\RSX\VK\vkutils\sampler.cpp" /> <ClCompile Include="Emu\RSX\VK\vkutils\sampler.cpp" />
<ClCompile Include="Emu\RSX\VK\vkutils\shared.cpp" /> <ClCompile Include="Emu\RSX\VK\vkutils\shared.cpp" />
<ClCompile Include="Emu\RSX\VK\vkutils\unique_resource.cpp" />
<ClCompile Include="Emu\RSX\VK\VKVertexBuffers.cpp" /> <ClCompile Include="Emu\RSX\VK\VKVertexBuffers.cpp" />
<ClCompile Include="Emu\RSX\VK\VKVertexProgram.cpp" /> <ClCompile Include="Emu\RSX\VK\VKVertexProgram.cpp" />
<ClCompile Include="Emu\RSX\VK\VKTextureCache.cpp" /> <ClCompile Include="Emu\RSX\VK\VKTextureCache.cpp" />

View file

@ -84,6 +84,9 @@
<ClCompile Include="Emu\RSX\VK\vkutils\ex.cpp"> <ClCompile Include="Emu\RSX\VK\vkutils\ex.cpp">
<Filter>vkutils</Filter> <Filter>vkutils</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Emu\RSX\VK\vkutils\unique_resource.cpp">
<Filter>vkutils</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h" /> <ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h" />
@ -206,6 +209,9 @@
<ClInclude Include="Emu\RSX\VK\vkutils\ex.h"> <ClInclude Include="Emu\RSX\VK\vkutils\ex.h">
<Filter>vkutils</Filter> <Filter>vkutils</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\RSX\VK\vkutils\unique_resource.h">
<Filter>vkutils</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="vkutils"> <Filter Include="vkutils">

View file

@ -1223,21 +1223,30 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
if (const std::string sstate = get_savestate_file(current_game.serial, current_game.path, 1); is_savestate_compatible(sstate)) if (const std::string sstate = get_savestate_file(current_game.serial, current_game.path, 1); is_savestate_compatible(sstate))
{ {
QAction* boot_state = menu.addAction(is_current_running_game const bool has_ambiguity = !get_savestate_file(current_game.serial, current_game.path, 2).empty();
? tr("&Reboot with savestate")
: tr("&Boot with savestate"));
connect(boot_state, &QAction::triggered, [this, gameinfo, sstate, current_game]
{
if (!get_savestate_file(current_game.serial, current_game.path, 2).empty())
{
// If there is any ambiguity, launch the savestate manager
Q_EMIT RequestSaveStateManager(gameinfo);
return;
}
QAction* boot_state = menu.addAction(is_current_running_game
? tr("&Reboot with last SaveState")
: tr("&Boot with last SaveState"));
connect(boot_state, &QAction::triggered, [this, gameinfo, sstate]
{
sys_log.notice("Booting savestate from gamelist per context menu..."); sys_log.notice("Booting savestate from gamelist per context menu...");
Q_EMIT RequestBoot(gameinfo, cfg_mode::custom, "", sstate); Q_EMIT RequestBoot(gameinfo, cfg_mode::custom, "", sstate);
}); });
if (has_ambiguity)
{
QAction* choose_state = menu.addAction(is_current_running_game
? tr("&Choose SaveState to reboot")
: tr("&Choose SaveState to boot"));
connect(choose_state, &QAction::triggered, [this, gameinfo]
{
// If there is any ambiguity, launch the savestate manager
Q_EMIT RequestSaveStateManager(gameinfo);
});
}
} }
menu.addSeparator(); menu.addSeparator();

View file

@ -664,9 +664,22 @@ namespace gui
return dateTime; return dateTime;
} }
QString format_datetime(const QDateTime& date, const QString& fmt) QString format_datetime(const QDateTime& date, const QString& fmt, bool is_relative, const QString& fmt_relative)
{ {
return date.toString(fmt); const qint64 exctrated_date = date.date().toJulianDay();
const qint64 current_date = QDate::currentDate().toJulianDay();
if (!is_relative || exctrated_date > current_date || current_date - exctrated_date >= 3)
{
return date.toString(fmt);
}
if (current_date == exctrated_date)
{
return QString("Today %1").arg(date.toString(fmt_relative));
}
return QString("%1 days ago %2").arg(current_date - exctrated_date).arg(date.toString(fmt_relative));
} }
QString format_timestamp(s64 time, const QString& fmt) QString format_timestamp(s64 time, const QString& fmt)

View file

@ -161,7 +161,7 @@ namespace gui
QDateTime datetime(s64 time); QDateTime datetime(s64 time);
// Convert a QDateTime to a readable string // Convert a QDateTime to a readable string
QString format_datetime(const QDateTime& date, const QString& fmt = "yyyy-MM-dd HH:mm:ss"); QString format_datetime(const QDateTime& date, const QString& fmt = "yyyy-MM-dd HH:mm:ss", bool is_relative = false, const QString& fmt_relative = "HH:mm:ss");
// Convert a timestamp to a readable string // Convert a timestamp to a readable string
QString format_timestamp(s64 time, const QString& fmt = "yyyy-MM-dd HH:mm:ss"); QString format_timestamp(s64 time, const QString& fmt = "yyyy-MM-dd HH:mm:ss");

View file

@ -549,33 +549,38 @@ void savestate_manager_dialog::StartSavestateLoadThreads()
return; return;
} }
std::vector<std::unique_ptr<game_savestates_data>> game_data(count); std::vector<std::unique_ptr<game_savestates_data>> game_data;
qRegisterMetaType<QVector<int>>("QVector<int>"); qRegisterMetaType<QVector<int>>("QVector<int>");
QList<int> indices; QList<int> indices;
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
indices.append(i); auto game_data_ptr = std::make_unique<game_savestates_data>();
game_data_ptr->title_id = folder_list[i].toStdString();
game_data[i] = std::make_unique<game_savestates_data>();
game_data[i]->title_id = folder_list[i].toStdString();
for (const game_info& gameinfo : m_game_info) for (const game_info& gameinfo : m_game_info)
{ {
if (gameinfo && gameinfo->info.serial == game_data[i]->title_id) if (gameinfo && gameinfo->info.serial == game_data_ptr->title_id)
{ {
game_data[i]->game_name = gameinfo->info.name; game_data_ptr->game_name = gameinfo->info.name;
game_data[i]->game_icon_path = gameinfo->info.icon_path; game_data_ptr->game_icon_path = gameinfo->info.icon_path;
break; break;
} }
} }
if (game_data[i]->game_name.empty()) if (!game_data_ptr->game_name.empty())
{ {
game_data[i]->game_name = game_data[i]->title_id; indices.append(game_data.size());
game_data.emplace_back(std::move(game_data_ptr));
} }
} }
if (game_data.empty())
{
RepaintUI(true);
return;
}
QFutureWatcher<void> future_watcher; QFutureWatcher<void> future_watcher;
progress_dialog progress_dialog(tr("Loading savestates"), tr("Loading savestates, please wait..."), tr("Cancel"), 0, 1, false, this, Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint); progress_dialog progress_dialog(tr("Loading savestates"), tr("Loading savestates, please wait..."), tr("Cancel"), 0, 1, false, this, Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
@ -681,7 +686,7 @@ void savestate_manager_dialog::PopulateSavestateTable()
const savestate_data& savestate = savestates[i]; const savestate_data& savestate = savestates[i];
m_savestate_table->setItem(i, static_cast<int>(gui::savestate_list_columns::name), new custom_table_widget_item(savestate.name)); m_savestate_table->setItem(i, static_cast<int>(gui::savestate_list_columns::name), new custom_table_widget_item(savestate.name));
m_savestate_table->setItem(i, static_cast<int>(gui::savestate_list_columns::compatible), new custom_table_widget_item(savestate.is_compatible ? tr("Compatible") : tr("Not compatible"), Qt::UserRole, savestate.is_compatible)); m_savestate_table->setItem(i, static_cast<int>(gui::savestate_list_columns::compatible), new custom_table_widget_item(savestate.is_compatible ? tr("Compatible") : tr("Not compatible"), Qt::UserRole, savestate.is_compatible));
m_savestate_table->setItem(i, static_cast<int>(gui::savestate_list_columns::date), new custom_table_widget_item(gui::utils::format_datetime(savestate.date), Qt::UserRole, savestate.date)); m_savestate_table->setItem(i, static_cast<int>(gui::savestate_list_columns::date), new custom_table_widget_item(gui::utils::format_datetime(savestate.date, "yyyy-MM-dd HH:mm", true, "HH:mm"), Qt::UserRole, savestate.date));
m_savestate_table->setItem(i, static_cast<int>(gui::savestate_list_columns::path), new custom_table_widget_item(savestate.path)); m_savestate_table->setItem(i, static_cast<int>(gui::savestate_list_columns::path), new custom_table_widget_item(savestate.path));
} }