mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
Merge branch 'master' into spu-giga-crash-fix
This commit is contained in:
commit
7c02f7e78b
35 changed files with 786 additions and 290 deletions
13
.ci/build-linux-aarch64.sh
Normal file → Executable file
13
.ci/build-linux-aarch64.sh
Normal file → Executable file
|
@ -12,9 +12,16 @@ git submodule -q update --init $(awk '/path/ && !/llvm/ && !/opencv/ { print $3
|
|||
|
||||
mkdir build && cd build || exit 1
|
||||
|
||||
export CC="${CLANG_BINARY}"
|
||||
export CXX="${CLANGXX_BINARY}"
|
||||
export LINKER="${LLD_BINARY}"
|
||||
if [ "$COMPILER" = "gcc" ]; then
|
||||
# These are set in the dockerfile
|
||||
export CC="${GCC_BINARY}"
|
||||
export CXX="${GXX_BINARY}"
|
||||
export LINKER=gold
|
||||
else
|
||||
export CC="${CLANG_BINARY}"
|
||||
export CXX="${CLANGXX_BINARY}"
|
||||
export LINKER="${LLD_BINARY}"
|
||||
fi
|
||||
export CFLAGS="$CFLAGS -fuse-ld=${LINKER}"
|
||||
export CXXFLAGS="$CXXFLAGS -fuse-ld=${LINKER}"
|
||||
|
||||
|
|
|
@ -103,16 +103,24 @@ COMM_HASH=$(git rev-parse --short=8 HEAD)
|
|||
# Format the above into filenames
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
AVVER="${COMM_TAG}-${COMM_HASH}"
|
||||
BUILD="rpcs3-v${AVVER}_win64.7z"
|
||||
BUILD_RAW="rpcs3-v${AVVER}_win64"
|
||||
BUILD="${BUILD_RAW}.7z"
|
||||
else
|
||||
AVVER="${COMM_TAG}-${COMM_COUNT}"
|
||||
BUILD="rpcs3-v${AVVER}-${COMM_HASH}_win64.7z"
|
||||
BUILD_RAW="rpcs3-v${AVVER}-${COMM_HASH}_win64"
|
||||
BUILD="${BUILD_RAW}.7z"
|
||||
fi
|
||||
|
||||
# BRANCH is used for experimental build warnings for pr builds, used in main_window.cpp.
|
||||
# BUILD is the name of the release artifact
|
||||
# BUILD_RAW is just filename
|
||||
# AVVER is used for GitHub releases, it is the version number.
|
||||
BRANCH="${REPO_NAME}/${REPO_BRANCH}"
|
||||
echo "BRANCH=$BRANCH" > .ci/ci-vars.env
|
||||
echo "BUILD=$BUILD" >> .ci/ci-vars.env
|
||||
echo "AVVER=$AVVER" >> .ci/ci-vars.env
|
||||
|
||||
# SC2129
|
||||
{
|
||||
echo "BRANCH=$BRANCH"
|
||||
echo "BUILD=$BUILD"
|
||||
echo "BUILD_RAW=$BUILD_RAW"
|
||||
echo "AVVER=$AVVER"
|
||||
} >> .ci/ci-vars.env
|
||||
|
|
165
.github/workflows/rpcs3.yml
vendored
Normal file
165
.github/workflows/rpcs3.yml
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
name: Build RPCS3
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- '.cirrus.yml'
|
||||
- '.azure-pipelines.yml'
|
||||
- 'README.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '.cirrus.yml'
|
||||
- '.azure-pipelines.yml'
|
||||
- 'README.md'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.ref }}-${{ github.event_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
BUILD_REPOSITORY_NAME: ${{ github.repository }}
|
||||
BUILD_SOURCEBRANCHNAME: ${{ github.ref_name }}
|
||||
BUILD_ARTIFACTSTAGINGDIRECTORY: ${{ github.workspace }}/build
|
||||
|
||||
jobs:
|
||||
Linux_Build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-24.04
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy:1.0"
|
||||
build_sh: "/rpcs3/.ci/build-linux.sh"
|
||||
compiler: clang
|
||||
- os: ubuntu-24.04
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy:1.0"
|
||||
build_sh: "/rpcs3/.ci/build-linux.sh"
|
||||
compiler: gcc
|
||||
- os: ubuntu-24.04-arm
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.0"
|
||||
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
|
||||
compiler: clang
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CCACHE_DIR: ${{ github.workspace }}/ccache
|
||||
CI_HAS_ARTIFACTS: true
|
||||
DEPLOY_APPIMAGE: true
|
||||
APPDIR: "/rpcs3/build/appdir"
|
||||
ARTDIR: "/root/artifacts"
|
||||
RELEASE_MESSAGE: "/rpcs3/GitHubReleaseMessage.txt"
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@main
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Cache
|
||||
uses: actions/cache@main
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ${{ runner.os }}-ccache-${{ matrix.compiler }}
|
||||
|
||||
- name: Docker setup and build
|
||||
run: |
|
||||
docker pull --quiet ${{ matrix.docker_img }}
|
||||
docker run \
|
||||
-v $PWD:/rpcs3 \
|
||||
--env-file .ci/docker.env \
|
||||
-v ${{ env.CCACHE_DIR }}:/root/.ccache \
|
||||
-v ${{ github.workspace }}/artifacts:/root/artifacts \
|
||||
${{ matrix.docker_img }} \
|
||||
${{ matrix.build_sh }}
|
||||
|
||||
- name: Upload artifacts
|
||||
#TODO: Upload artifact to release repository
|
||||
#condition for release
|
||||
#if: |
|
||||
# github.event_name != 'pull_request' &&
|
||||
# github.repository == 'RPCS3/rpcs3' &&
|
||||
# github.ref == 'refs/heads/master' &&
|
||||
# matrix.compiler == 'clang'
|
||||
uses: actions/upload-artifact@main
|
||||
with:
|
||||
name: RPCS3 for Linux (${{ runner.arch }}, ${{ matrix.compiler }})
|
||||
path: ${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }}/*.AppImage
|
||||
compression-level: 0
|
||||
|
||||
Windows_Build:
|
||||
runs-on: windows-2025
|
||||
env:
|
||||
COMPILER: msvc
|
||||
QT_VER_MAIN: '6'
|
||||
QT_VER: '6.8.1'
|
||||
QT_VER_MSVC: 'msvc2022'
|
||||
QT_DATE: '202411221531'
|
||||
VULKAN_VER: '1.3.268.0'
|
||||
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
|
||||
CACHE_DIR: ./cache
|
||||
steps:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@main
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup env
|
||||
run: |
|
||||
echo "QTDIR=C:\Qt\${{ env.QT_VER }}\${{ env.QT_VER_MSVC }}_64" >> ${{ github.env }}
|
||||
echo "VULKAN_SDK=C:\VulkanSDK\${{ env.VULKAN_VER }}" >> ${{ github.env }}
|
||||
|
||||
- name: Get Cache Keys
|
||||
shell: bash
|
||||
run: .ci/get_keys-windows.sh
|
||||
|
||||
- name: Setup Cache
|
||||
uses: actions/cache@main
|
||||
with:
|
||||
path: ${{ env.CACHE_DIR }}
|
||||
key: "${{ runner.os }}-${{ env.COMPILER }}-${{ env.QT_VER }}-${{ env.VULKAN_SDK_SHA }}-${{ hashFiles('llvm.lock') }}-${{ hashFiles('glslang.lock') }}"
|
||||
restore-keys: ${{ runner.os }}-${{ env.COMPILER }}
|
||||
|
||||
- name: Download and unpack dependencies
|
||||
shell: bash
|
||||
run: .ci/setup-windows.sh
|
||||
|
||||
- name: Export Variables
|
||||
shell: bash
|
||||
run: |
|
||||
while IFS='=' read -r key val; do
|
||||
# Skip lines that are empty or start with '#'
|
||||
[[ -z "$key" || "$key" =~ ^# ]] && continue
|
||||
echo "$key=$val" >> "${{ github.env }}"
|
||||
done < .ci/ci-vars.env
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@main
|
||||
|
||||
- name: Compile RPCS3
|
||||
run: msbuild rpcs3.sln /p:Configuration=Release /p:Platform=x64
|
||||
|
||||
- name: Pack up build artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }}
|
||||
.ci/deploy-windows.sh
|
||||
|
||||
- name: Upload artifacts (7z)
|
||||
#TODO: Upload artifact to release repository
|
||||
#condition for release
|
||||
#if: |
|
||||
# github.event_name != 'pull_request' &&
|
||||
# github.repository == 'RPCS3/rpcs3' &&
|
||||
# github.ref == 'refs/heads/master'
|
||||
uses: actions/upload-artifact@main
|
||||
with:
|
||||
name: RPCS3 for Windows (MSVC)
|
||||
# 7z
|
||||
# 7z.sha256
|
||||
path: |
|
||||
${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }}/${{ env.BUILD }}
|
||||
${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }}/${{ env.BUILD }}.sha256
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -28,10 +28,6 @@
|
|||
path = 3rdparty/pugixml
|
||||
url = ../../zeux/pugixml.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/xxHash"]
|
||||
path = 3rdparty/xxHash
|
||||
url = ../../Cyan4973/xxHash.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/yaml-cpp"]
|
||||
path = 3rdparty/yaml-cpp/yaml-cpp
|
||||
url = ../../RPCS3/yaml-cpp.git
|
||||
|
|
14
3rdparty/CMakeLists.txt
vendored
14
3rdparty/CMakeLists.txt
vendored
|
@ -97,19 +97,6 @@ target_link_libraries(3rdparty_glslang INTERFACE SPIRV)
|
|||
add_subdirectory(yaml-cpp)
|
||||
|
||||
|
||||
# xxHash
|
||||
if (USE_SYSTEM_XXHASH)
|
||||
pkg_check_modules(XXHASH REQUIRED IMPORTED_TARGET libxxhash)
|
||||
add_library(xxhash INTERFACE)
|
||||
target_link_libraries(xxhash INTERFACE PkgConfig::XXHASH)
|
||||
else()
|
||||
set(XXHASH_BUNDLED_MODE ON)
|
||||
set(XXHASH_BUILD_XXHSUM OFF)
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Make xxHash build static libs")
|
||||
add_subdirectory(xxHash/cmake_unofficial EXCLUDE_FROM_ALL)
|
||||
target_include_directories(xxhash INTERFACE xxHash)
|
||||
endif()
|
||||
|
||||
# OpenGL
|
||||
|
||||
find_package(OpenGL REQUIRED OPTIONAL_COMPONENTS EGL)
|
||||
|
@ -364,7 +351,6 @@ add_library(3rdparty::flatbuffers ALIAS 3rdparty_flatbuffers)
|
|||
add_library(3rdparty::pugixml ALIAS pugixml)
|
||||
add_library(3rdparty::glslang ALIAS 3rdparty_glslang)
|
||||
add_library(3rdparty::yaml-cpp ALIAS yaml-cpp)
|
||||
add_library(3rdparty::xxhash ALIAS xxhash)
|
||||
add_library(3rdparty::hidapi ALIAS 3rdparty_hidapi)
|
||||
add_library(3rdparty::libpng ALIAS ${LIBPNG_TARGET})
|
||||
add_library(3rdparty::opengl ALIAS 3rdparty_opengl)
|
||||
|
|
170
3rdparty/bcdec/bcdec.hpp
vendored
Normal file
170
3rdparty/bcdec/bcdec.hpp
vendored
Normal file
|
@ -0,0 +1,170 @@
|
|||
// Based on https://github.com/iOrange/bcdec/blob/963c5e56b7a335e066cff7d16a3de75f4e8ad366/bcdec.h
|
||||
// provides functions to decompress blocks of BC compressed images
|
||||
//
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// MIT LICENSE
|
||||
// ===========
|
||||
// Copyright (c) 2022 Sergii Kudlai
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/types.hpp>
|
||||
|
||||
static void bcdec__color_block(const u8* compressedBlock, u8* dstColors, int destinationPitch, bool onlyOpaqueMode) {
|
||||
u16 c0, c1;
|
||||
u32 refColors[4]; /* 0xAABBGGRR */
|
||||
u32 colorIndices;
|
||||
u32 r0, g0, b0, r1, g1, b1, r, g, b;
|
||||
|
||||
c0 = *reinterpret_cast<const u16*>(compressedBlock);
|
||||
c1 = *(reinterpret_cast<const u16*>(compressedBlock) + 1);
|
||||
|
||||
/* Unpack 565 ref colors */
|
||||
r0 = (c0 >> 11) & 0x1F;
|
||||
g0 = (c0 >> 5) & 0x3F;
|
||||
b0 = c0 & 0x1F;
|
||||
|
||||
r1 = (c1 >> 11) & 0x1F;
|
||||
g1 = (c1 >> 5) & 0x3F;
|
||||
b1 = c1 & 0x1F;
|
||||
|
||||
/* Expand 565 ref colors to 888 */
|
||||
r = (r0 * 527 + 23) >> 6;
|
||||
g = (g0 * 259 + 33) >> 6;
|
||||
b = (b0 * 527 + 23) >> 6;
|
||||
refColors[0] = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
|
||||
r = (r1 * 527 + 23) >> 6;
|
||||
g = (g1 * 259 + 33) >> 6;
|
||||
b = (b1 * 527 + 23) >> 6;
|
||||
refColors[1] = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
|
||||
if (c0 > c1 || onlyOpaqueMode)
|
||||
{ /* Standard BC1 mode (also BC3 color block uses ONLY this mode) */
|
||||
/* color_2 = 2/3*color_0 + 1/3*color_1
|
||||
color_3 = 1/3*color_0 + 2/3*color_1 */
|
||||
r = ((2 * r0 + r1) * 351 + 61) >> 7;
|
||||
g = ((2 * g0 + g1) * 2763 + 1039) >> 11;
|
||||
b = ((2 * b0 + b1) * 351 + 61) >> 7;
|
||||
refColors[2] = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
|
||||
r = ((r0 + r1 * 2) * 351 + 61) >> 7;
|
||||
g = ((g0 + g1 * 2) * 2763 + 1039) >> 11;
|
||||
b = ((b0 + b1 * 2) * 351 + 61) >> 7;
|
||||
refColors[3] = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
else
|
||||
{ /* Quite rare BC1A mode */
|
||||
/* color_2 = 1/2*color_0 + 1/2*color_1;
|
||||
color_3 = 0; */
|
||||
r = ((r0 + r1) * 1053 + 125) >> 8;
|
||||
g = ((g0 + g1) * 4145 + 1019) >> 11;
|
||||
b = ((b0 + b1) * 1053 + 125) >> 8;
|
||||
refColors[2] = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
|
||||
refColors[3] = 0x00000000;
|
||||
}
|
||||
|
||||
colorIndices = *reinterpret_cast<const u32*>(compressedBlock + 4);
|
||||
|
||||
/* Fill out the decompressed color block */
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
int idx = colorIndices & 0x03;
|
||||
*reinterpret_cast<u32*>(dstColors + j * 4) = refColors[idx];
|
||||
colorIndices >>= 2;
|
||||
}
|
||||
|
||||
dstColors += destinationPitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void bcdec__sharp_alpha_block(const u16* alpha, u8* decompressed, int destinationPitch) {
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
decompressed[j * 4] = ((alpha[i] >> (4 * j)) & 0x0F) * 17;
|
||||
}
|
||||
decompressed += destinationPitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void bcdec__smooth_alpha_block(const u8* compressedBlock, u8* decompressed, int destinationPitch) {
|
||||
u8 alpha[8];
|
||||
u64 block = *reinterpret_cast<const u64*>(compressedBlock);
|
||||
u64 indices;
|
||||
|
||||
alpha[0] = block & 0xFF;
|
||||
alpha[1] = (block >> 8) & 0xFF;
|
||||
|
||||
if (alpha[0] > alpha[1])
|
||||
{
|
||||
/* 6 interpolated alpha values. */
|
||||
alpha[2] = (6 * alpha[0] + alpha[1]) / 7; /* 6/7*alpha_0 + 1/7*alpha_1 */
|
||||
alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7; /* 5/7*alpha_0 + 2/7*alpha_1 */
|
||||
alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7; /* 4/7*alpha_0 + 3/7*alpha_1 */
|
||||
alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7; /* 3/7*alpha_0 + 4/7*alpha_1 */
|
||||
alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7; /* 2/7*alpha_0 + 5/7*alpha_1 */
|
||||
alpha[7] = ( alpha[0] + 6 * alpha[1]) / 7; /* 1/7*alpha_0 + 6/7*alpha_1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 4 interpolated alpha values. */
|
||||
alpha[2] = (4 * alpha[0] + alpha[1]) / 5; /* 4/5*alpha_0 + 1/5*alpha_1 */
|
||||
alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5; /* 3/5*alpha_0 + 2/5*alpha_1 */
|
||||
alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5; /* 2/5*alpha_0 + 3/5*alpha_1 */
|
||||
alpha[5] = ( alpha[0] + 4 * alpha[1]) / 5; /* 1/5*alpha_0 + 4/5*alpha_1 */
|
||||
alpha[6] = 0x00;
|
||||
alpha[7] = 0xFF;
|
||||
}
|
||||
|
||||
indices = block >> 16;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
decompressed[j * 4] = alpha[indices & 0x07];
|
||||
indices >>= 3;
|
||||
}
|
||||
decompressed += destinationPitch;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bcdec_bc1(const u8* compressedBlock, u8* decompressedBlock, int destinationPitch) {
|
||||
bcdec__color_block(compressedBlock, decompressedBlock, destinationPitch, false);
|
||||
}
|
||||
|
||||
static inline void bcdec_bc2(const u8* compressedBlock, u8* decompressedBlock, int destinationPitch) {
|
||||
bcdec__color_block(compressedBlock + 8, decompressedBlock, destinationPitch, true);
|
||||
bcdec__sharp_alpha_block(reinterpret_cast<const u16*>(compressedBlock), decompressedBlock + 3, destinationPitch);
|
||||
}
|
||||
|
||||
static inline void bcdec_bc3(const u8* compressedBlock, u8* decompressedBlock, int destinationPitch) {
|
||||
bcdec__color_block(compressedBlock + 8, decompressedBlock, destinationPitch, true);
|
||||
bcdec__smooth_alpha_block(compressedBlock, decompressedBlock + 3, destinationPitch);
|
||||
}
|
||||
|
1
3rdparty/xxHash
vendored
1
3rdparty/xxHash
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit e626a72bc2321cd320e953a0ccf1584cad60f363
|
65
3rdparty/xxhash.vcxproj
vendored
65
3rdparty/xxhash.vcxproj
vendored
|
@ -1,65 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{939FE206-1182-ABC3-1234-FEAB88E98404}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default_macros.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_default.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="xxHash/xxhash.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="LICENSE" />
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="xxHash/xxhash.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -3,7 +3,7 @@
|
|||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IncludePath>.\;..\;..\3rdparty\asmjit\asmjit\src;..\..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\libpng\libpng;..\3rdparty\GL;..\3rdparty\stblib\stb;..\3rdparty\openal\openal-soft\include\AL;..\3rdparty\pugixml\src;..\3rdparty\hidapi\hidapi;..\3rdparty\Optional;..\3rdparty\xxhash</IncludePath>
|
||||
<IncludePath>.\;..\;..\3rdparty\asmjit\asmjit\src;..\..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);..\3rdparty\libpng\libpng;..\3rdparty\GL;..\3rdparty\stblib\stb;..\3rdparty\openal\openal-soft\include\AL;..\3rdparty\pugixml\src;..\3rdparty\hidapi\hidapi</IncludePath>
|
||||
<OutDir>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\</OutDir>
|
||||
<LibraryPath>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)</LibraryPath>
|
||||
<IntDir>$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<AdditionalOptions>/utf-8 /Zc:throwingNew- /constexpr:steps16777216 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>xxhash.lib;ws2_32.lib;Iphlpapi.lib;Bcrypt.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;Iphlpapi.lib;Bcrypt.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\ffmpeg\lib\windows\x86_64</AdditionalLibraryDirectories>
|
||||
<StackReserveSize>8388608</StackReserveSize>
|
||||
<StackCommitSize>1048576</StackCommitSize>
|
||||
|
|
|
@ -10,7 +10,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emucore", "rpcs3\emucore.vc
|
|||
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {3C67A2FF-4710-402A-BE3E-31B0CB0576DF}
|
||||
{5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0} = {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}
|
||||
{8846A9AA-5539-4C91-8301-F54260E1A07A} = {8846A9AA-5539-4C91-8301-F54260E1A07A}
|
||||
{939FE206-1182-ABC3-1234-FEAB88E98404} = {939FE206-1182-ABC3-1234-FEAB88E98404}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "llvm_build", "3rdparty\llvm\llvm_build.vcxproj", "{8BC303AB-25BE-4276-8E57-73F171B2D672}"
|
||||
|
@ -67,8 +66,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxpro
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "3rdparty\hidapi\hidapi.vcxproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xxhash", "3rdparty\xxhash.vcxproj", "{939FE206-1182-ABC3-1234-FEAB88E98404}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "3rdparty\libusb\libusb_static.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "3rdparty\wolfssl\wolfssl.vcxproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}"
|
||||
|
@ -161,10 +158,6 @@ Global
|
|||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.Build.0 = Debug|x64
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.ActiveCfg = Release|x64
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.Build.0 = Release|x64
|
||||
{939FE206-1182-ABC3-1234-FEAB88E98404}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{939FE206-1182-ABC3-1234-FEAB88E98404}.Debug|x64.Build.0 = Debug|x64
|
||||
{939FE206-1182-ABC3-1234-FEAB88E98404}.Release|x64.ActiveCfg = Release|x64
|
||||
{939FE206-1182-ABC3-1234-FEAB88E98404}.Release|x64.Build.0 = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
|
||||
|
@ -236,7 +229,6 @@ Global
|
|||
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
|
||||
{FDC361C5-7734-493B-8CFB-037308B35122} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{939FE206-1182-ABC3-1234-FEAB88E98404} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{73973223-5EE8-41CA-8E88-1D60E89A237B} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
|
|
|
@ -641,7 +641,7 @@ target_link_libraries(rpcs3_emu
|
|||
3rdparty::vulkan 3rdparty::glew
|
||||
3rdparty::libusb 3rdparty::wolfssl
|
||||
PRIVATE
|
||||
3rdparty::glslang 3rdparty::xxhash
|
||||
3rdparty::glslang
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <Emu/Cell/lv2/sys_event.h>
|
||||
|
||||
#include <numeric>
|
||||
#include <cmath>
|
||||
|
||||
#include "3rdparty/OpenAL/openal-soft/include/AL/alext.h"
|
||||
|
||||
|
@ -575,6 +576,28 @@ bool microphone_device::has_data() const
|
|||
return mic_registered && mic_opened && mic_started && (rbuf_raw.has_data() || rbuf_dsp.has_data());
|
||||
}
|
||||
|
||||
f32 microphone_device::calculate_energy_level()
|
||||
{
|
||||
const auto& buffer = device_type == microphone_handler::real_singstar ? ::at32(devices, 0).buf : temp_buf;
|
||||
const size_t num_samples = buffer.size() / sizeof(s16);
|
||||
|
||||
f64 sum_squares = 0.0;
|
||||
|
||||
for (usz i = 0; i < num_samples; i++)
|
||||
{
|
||||
const be_t<s16> sample = read_from_ptr<be_t<s16>>(buffer, i * sizeof(s16));
|
||||
const f64 normalized_sample = static_cast<f64>(sample) / -std::numeric_limits<s16>::min();
|
||||
sum_squares += normalized_sample * normalized_sample;
|
||||
}
|
||||
|
||||
const f32 rms = std::sqrt(sum_squares / num_samples);
|
||||
const f32 decibels_max = 90.0f;
|
||||
const f32 decibels_relative = 20.0f * std::log10(std::max(rms, 0.00001f));
|
||||
const f32 decibels = decibels_max + (decibels_relative * 0.5f);
|
||||
|
||||
return std::clamp(decibels, 40.0f, decibels_max);
|
||||
}
|
||||
|
||||
u32 microphone_device::capture_audio()
|
||||
{
|
||||
ensure(sample_size > 0);
|
||||
|
@ -1089,7 +1112,7 @@ error_code cellMicGetSignalState(s32 dev_num, CellMicSignalState sig_state, vm::
|
|||
*fval = 1.0f; // No gain applied
|
||||
break;
|
||||
case CELLMIC_SIGSTATE_MICENG:
|
||||
*fval = 40.0f; // 40 decibels
|
||||
*fval = device.calculate_energy_level();
|
||||
break;
|
||||
case CELLMIC_SIGSTATE_SPKENG:
|
||||
*fval = 10.0f; // 10 decibels
|
||||
|
|
|
@ -289,6 +289,8 @@ public:
|
|||
void update_audio();
|
||||
bool has_data() const;
|
||||
|
||||
f32 calculate_energy_level();
|
||||
|
||||
bool is_registered() const { return mic_registered; }
|
||||
bool is_opened() const { return mic_opened; }
|
||||
bool is_started() const { return mic_started; }
|
||||
|
|
|
@ -854,6 +854,10 @@ namespace np
|
|||
room_msg_cb_ctx = 0;
|
||||
room_msg_cb_arg = {};
|
||||
|
||||
presence_self.pr_status = {};
|
||||
presence_self.pr_data = {};
|
||||
presence_self.advertised = false;
|
||||
|
||||
if (g_cfg.net.psn_status == np_psn_status::psn_rpcn)
|
||||
{
|
||||
rpcn_log.notice("Setting RPCN state to disconnected!");
|
||||
|
@ -1157,21 +1161,23 @@ namespace np
|
|||
auto notifications = rpcn->get_notifications();
|
||||
for (auto& notif : notifications)
|
||||
{
|
||||
vec_stream noti_data(notif.second);
|
||||
|
||||
switch (notif.first)
|
||||
{
|
||||
case rpcn::NotificationType::UserJoinedRoom: notif_user_joined_room(notif.second); break;
|
||||
case rpcn::NotificationType::UserLeftRoom: notif_user_left_room(notif.second); break;
|
||||
case rpcn::NotificationType::RoomDestroyed: notif_room_destroyed(notif.second); break;
|
||||
case rpcn::NotificationType::UpdatedRoomDataInternal: notif_updated_room_data_internal(notif.second); break;
|
||||
case rpcn::NotificationType::UpdatedRoomMemberDataInternal: notif_updated_room_member_data_internal(notif.second); break;
|
||||
case rpcn::NotificationType::RoomMessageReceived: notif_room_message_received(notif.second); break;
|
||||
case rpcn::NotificationType::SignalingHelper: notif_signaling_helper(notif.second); break;
|
||||
case rpcn::NotificationType::MemberJoinedRoomGUI: notif_member_joined_room_gui(notif.second); break;
|
||||
case rpcn::NotificationType::MemberLeftRoomGUI: notif_member_left_room_gui(notif.second); break;
|
||||
case rpcn::NotificationType::RoomDisappearedGUI: notif_room_disappeared_gui(notif.second); break;
|
||||
case rpcn::NotificationType::RoomOwnerChangedGUI: notif_room_owner_changed_gui(notif.second); break;
|
||||
case rpcn::NotificationType::UserKickedGUI: notif_user_kicked_gui(notif.second); break;
|
||||
case rpcn::NotificationType::QuickMatchCompleteGUI: notif_quickmatch_complete_gui(notif.second); break;
|
||||
case rpcn::NotificationType::UserJoinedRoom: notif_user_joined_room(noti_data); break;
|
||||
case rpcn::NotificationType::UserLeftRoom: notif_user_left_room(noti_data); break;
|
||||
case rpcn::NotificationType::RoomDestroyed: notif_room_destroyed(noti_data); break;
|
||||
case rpcn::NotificationType::UpdatedRoomDataInternal: notif_updated_room_data_internal(noti_data); break;
|
||||
case rpcn::NotificationType::UpdatedRoomMemberDataInternal: notif_updated_room_member_data_internal(noti_data); break;
|
||||
case rpcn::NotificationType::RoomMessageReceived: notif_room_message_received(noti_data); break;
|
||||
case rpcn::NotificationType::SignalingHelper: notif_signaling_helper(noti_data); break;
|
||||
case rpcn::NotificationType::MemberJoinedRoomGUI: notif_member_joined_room_gui(noti_data); break;
|
||||
case rpcn::NotificationType::MemberLeftRoomGUI: notif_member_left_room_gui(noti_data); break;
|
||||
case rpcn::NotificationType::RoomDisappearedGUI: notif_room_disappeared_gui(noti_data); break;
|
||||
case rpcn::NotificationType::RoomOwnerChangedGUI: notif_room_owner_changed_gui(noti_data); break;
|
||||
case rpcn::NotificationType::UserKickedGUI: notif_user_kicked_gui(noti_data); break;
|
||||
case rpcn::NotificationType::QuickMatchCompleteGUI: notif_quickmatch_complete_gui(noti_data); break;
|
||||
default: fmt::throw_exception("Unknown notification(%d) received!", notif.first); break;
|
||||
}
|
||||
}
|
||||
|
@ -1536,7 +1542,7 @@ namespace np
|
|||
}
|
||||
}
|
||||
|
||||
if (send_update && is_psn_active)
|
||||
if (is_psn_active && (!presence_self.advertised || send_update))
|
||||
{
|
||||
std::lock_guard lock(mutex_rpcn);
|
||||
|
||||
|
@ -1545,6 +1551,7 @@ namespace np
|
|||
return;
|
||||
}
|
||||
|
||||
presence_self.advertised = true;
|
||||
rpcn->send_presence(presence_self.pr_com_id, presence_self.pr_title, presence_self.pr_status, presence_self.pr_comment, presence_self.pr_data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -293,22 +293,22 @@ namespace np
|
|||
bool error_and_disconnect(const std::string& error_msg);
|
||||
|
||||
// Notification handlers
|
||||
void notif_user_joined_room(std::vector<u8>& data);
|
||||
void notif_user_left_room(std::vector<u8>& data);
|
||||
void notif_room_destroyed(std::vector<u8>& data);
|
||||
void notif_updated_room_data_internal(std::vector<u8>& data);
|
||||
void notif_updated_room_member_data_internal(std::vector<u8>& data);
|
||||
void notif_signaling_helper(std::vector<u8>& data);
|
||||
void notif_room_message_received(std::vector<u8>& data);
|
||||
void notif_user_joined_room(vec_stream& noti);
|
||||
void notif_user_left_room(vec_stream& noti);
|
||||
void notif_room_destroyed(vec_stream& noti);
|
||||
void notif_updated_room_data_internal(vec_stream& noti);
|
||||
void notif_updated_room_member_data_internal(vec_stream& noti);
|
||||
void notif_signaling_helper(vec_stream& noti);
|
||||
void notif_room_message_received(vec_stream& noti);
|
||||
|
||||
void generic_gui_notification_handler(std::vector<u8>& data, std::string_view name, s32 notification_type);
|
||||
void generic_gui_notification_handler(vec_stream& noti, std::string_view name, s32 notification_type);
|
||||
|
||||
void notif_member_joined_room_gui(std::vector<u8>& data);
|
||||
void notif_member_left_room_gui(std::vector<u8>& data);
|
||||
void notif_room_disappeared_gui(std::vector<u8>& data);
|
||||
void notif_room_owner_changed_gui(std::vector<u8>& data);
|
||||
void notif_user_kicked_gui(std::vector<u8>& data);
|
||||
void notif_quickmatch_complete_gui(std::vector<u8>& data);
|
||||
void notif_member_joined_room_gui(vec_stream& noti);
|
||||
void notif_member_left_room_gui(vec_stream& noti);
|
||||
void notif_room_disappeared_gui(vec_stream& noti);
|
||||
void notif_room_owner_changed_gui(vec_stream& noti);
|
||||
void notif_user_kicked_gui(vec_stream& noti);
|
||||
void notif_quickmatch_complete_gui(vec_stream& noti);
|
||||
|
||||
// Reply handlers
|
||||
void reply_get_world_list(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
|
||||
|
@ -509,6 +509,7 @@ namespace np
|
|||
std::string pr_status;
|
||||
std::string pr_comment;
|
||||
std::vector<u8> pr_data;
|
||||
atomic_t<bool> advertised = false;
|
||||
} presence_self;
|
||||
|
||||
player_history& get_player_and_set_timestamp(const SceNpId& npid, u64 timestamp);
|
||||
|
|
|
@ -13,9 +13,8 @@ LOG_CHANNEL(rpcn_log, "rpcn");
|
|||
|
||||
namespace np
|
||||
{
|
||||
void np_handler::notif_user_joined_room(std::vector<u8>& data)
|
||||
void np_handler::notif_user_joined_room(vec_stream& noti)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
const auto* notification = noti.get_flatbuffer<NotificationUserJoinedRoom>();
|
||||
|
||||
if (noti.is_error())
|
||||
|
@ -72,9 +71,8 @@ namespace np
|
|||
}
|
||||
}
|
||||
|
||||
void np_handler::notif_user_left_room(std::vector<u8>& data)
|
||||
void np_handler::notif_user_left_room(vec_stream& noti)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
u64 room_id = noti.get<u64>();
|
||||
const auto* update_info = noti.get_flatbuffer<RoomMemberUpdateInfo>();
|
||||
|
||||
|
@ -112,9 +110,8 @@ namespace np
|
|||
}
|
||||
}
|
||||
|
||||
void np_handler::notif_room_destroyed(std::vector<u8>& data)
|
||||
void np_handler::notif_room_destroyed(vec_stream& noti)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
u64 room_id = noti.get<u64>();
|
||||
const auto* update_info = noti.get_flatbuffer<RoomUpdateInfo>();
|
||||
|
||||
|
@ -146,9 +143,8 @@ namespace np
|
|||
}
|
||||
}
|
||||
|
||||
void np_handler::notif_updated_room_data_internal(std::vector<u8>& data)
|
||||
void np_handler::notif_updated_room_data_internal(vec_stream& noti)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
SceNpMatching2RoomId room_id = noti.get<u64>();
|
||||
const auto* update_info = noti.get_flatbuffer<RoomDataInternalUpdateInfo>();
|
||||
|
||||
|
@ -182,9 +178,8 @@ namespace np
|
|||
}
|
||||
}
|
||||
|
||||
void np_handler::notif_updated_room_member_data_internal(std::vector<u8>& data)
|
||||
void np_handler::notif_updated_room_member_data_internal(vec_stream& noti)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
SceNpMatching2RoomId room_id = noti.get<u64>();
|
||||
const auto* update_info = noti.get_flatbuffer<RoomMemberDataInternalUpdateInfo>();
|
||||
|
||||
|
@ -221,9 +216,8 @@ namespace np
|
|||
}
|
||||
}
|
||||
|
||||
void np_handler::notif_room_message_received(std::vector<u8>& data)
|
||||
void np_handler::notif_room_message_received(vec_stream& noti)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
u64 room_id = noti.get<u64>();
|
||||
u16 member_id = noti.get<u16>();
|
||||
const auto* message_info = noti.get_flatbuffer<RoomMessageInfo>();
|
||||
|
@ -254,29 +248,28 @@ namespace np
|
|||
}
|
||||
}
|
||||
|
||||
void np_handler::notif_signaling_helper(std::vector<u8>& data)
|
||||
void np_handler::notif_signaling_helper(vec_stream& noti)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
const u32 addr_p2p = noti.get<u32>();
|
||||
const u32 port_p2p = noti.get<u16>();
|
||||
const std::string str_npid = noti.get_string(false);
|
||||
const auto* matching_info = noti.get_flatbuffer<MatchingSignalingInfo>();
|
||||
|
||||
if (noti.is_error())
|
||||
if (noti.is_error() || !matching_info->addr() || !matching_info->npid() || !matching_info->addr()->ip())
|
||||
{
|
||||
rpcn_log.error("Received faulty SignalingHelper notification");
|
||||
return;
|
||||
}
|
||||
|
||||
SceNpId npid_p2p;
|
||||
string_to_npid(str_npid, npid_p2p);
|
||||
string_to_npid(matching_info->npid()->string_view(), npid_p2p);
|
||||
|
||||
const u32 addr_p2p = register_ip(matching_info->addr()->ip());
|
||||
const u16 port_p2p = matching_info->addr()->port();
|
||||
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
sigh.send_information_packets(addr_p2p, port_p2p, npid_p2p);
|
||||
}
|
||||
|
||||
void np_handler::generic_gui_notification_handler(std::vector<u8>& data, std::string_view name, s32 notification_type)
|
||||
void np_handler::generic_gui_notification_handler(vec_stream& noti, std::string_view name, s32 notification_type)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
const auto* update_info = noti.get_flatbuffer<MatchingRoomStatus>();
|
||||
|
||||
if (noti.is_error())
|
||||
|
@ -329,36 +322,35 @@ namespace np
|
|||
ctx->queue_callback(req_id, notification_type, 0);
|
||||
}
|
||||
|
||||
void np_handler::notif_member_joined_room_gui(std::vector<u8>& data)
|
||||
void np_handler::notif_member_joined_room_gui(vec_stream& noti)
|
||||
{
|
||||
return generic_gui_notification_handler(data, "MemberJoinedRoomGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_NEW_MEMBER);
|
||||
return generic_gui_notification_handler(noti, "MemberJoinedRoomGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_NEW_MEMBER);
|
||||
}
|
||||
|
||||
void np_handler::notif_member_left_room_gui(std::vector<u8>& data)
|
||||
void np_handler::notif_member_left_room_gui(vec_stream& noti)
|
||||
{
|
||||
return generic_gui_notification_handler(data, "MemberLeftRoomGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_MEMBER_LEAVE);
|
||||
return generic_gui_notification_handler(noti, "MemberLeftRoomGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_MEMBER_LEAVE);
|
||||
}
|
||||
|
||||
void np_handler::notif_room_disappeared_gui(std::vector<u8>& data)
|
||||
void np_handler::notif_room_disappeared_gui(vec_stream& noti)
|
||||
{
|
||||
return generic_gui_notification_handler(data, "RoomDisappearedGUI", SCE_NP_MATCHING_EVENT_ROOM_DISAPPEARED);
|
||||
return generic_gui_notification_handler(noti, "RoomDisappearedGUI", SCE_NP_MATCHING_EVENT_ROOM_DISAPPEARED);
|
||||
}
|
||||
|
||||
void np_handler::notif_room_owner_changed_gui(std::vector<u8>& data)
|
||||
void np_handler::notif_room_owner_changed_gui(vec_stream& noti)
|
||||
{
|
||||
return generic_gui_notification_handler(data, "RoomOwnerChangedGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_OWNER_CHANGE);
|
||||
return generic_gui_notification_handler(noti, "RoomOwnerChangedGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_OWNER_CHANGE);
|
||||
}
|
||||
|
||||
void np_handler::notif_user_kicked_gui(std::vector<u8>& data)
|
||||
void np_handler::notif_user_kicked_gui(vec_stream& noti)
|
||||
{
|
||||
return generic_gui_notification_handler(data, "UserKickedGUI", SCE_NP_MATCHING_EVENT_ROOM_KICKED);
|
||||
return generic_gui_notification_handler(noti, "UserKickedGUI", SCE_NP_MATCHING_EVENT_ROOM_KICKED);
|
||||
}
|
||||
|
||||
void gui_epilog(const shared_ptr<matching_ctx>& ctx);
|
||||
|
||||
void np_handler::notif_quickmatch_complete_gui(std::vector<u8>& data)
|
||||
void np_handler::notif_quickmatch_complete_gui(vec_stream& noti)
|
||||
{
|
||||
vec_stream noti(data);
|
||||
const auto* update_info = noti.get_flatbuffer<MatchingRoomStatus>();
|
||||
|
||||
if (noti.is_error())
|
||||
|
|
|
@ -252,7 +252,7 @@ namespace np
|
|||
case rpcn::ErrorType::RoomPasswordMismatch: error_code = SCE_NP_MATCHING2_SERVER_ERROR_PASSWORD_MISMATCH; break;
|
||||
case rpcn::ErrorType::RoomGroupFull: error_code = SCE_NP_MATCHING2_SERVER_ERROR_GROUP_FULL; break;
|
||||
case rpcn::ErrorType::RoomGroupJoinLabelNotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_GROUP; break;
|
||||
default: fmt::throw_exception("Unexpected error in reply to JoinRoom: %d", static_cast<u8>(error)); ;
|
||||
default: fmt::throw_exception("Unexpected error in reply to JoinRoom: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
if (error_code != 0)
|
||||
|
@ -334,8 +334,9 @@ namespace np
|
|||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::NoError: break;
|
||||
case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; // Unsure if this should return another error(missing user in room has no appropriate error code)
|
||||
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
|
||||
default: fmt::throw_exception("Unexpected error in reply to LeaveRoom: %d", static_cast<u8>(error)); ;
|
||||
default: fmt::throw_exception("Unexpected error in reply to LeaveRoom: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
if (error_code != CELL_OK)
|
||||
|
@ -549,7 +550,7 @@ namespace np
|
|||
{
|
||||
case rpcn::ErrorType::NoError: break;
|
||||
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
|
||||
default: fmt::throw_exception("Unexpected error in reply to GetRoomDataInternal: %d", static_cast<u8>(error)); ;
|
||||
default: fmt::throw_exception("Unexpected error in reply to GetRoomDataInternal: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
cb_info_opt->queue_callback(req_id, 0, error_code, 0);
|
||||
|
@ -583,7 +584,7 @@ namespace np
|
|||
case rpcn::ErrorType::NoError: break;
|
||||
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
|
||||
case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_USER; break;
|
||||
default: fmt::throw_exception("Unexpected error in reply to GetRoomMemberDataInternal: %d", static_cast<u8>(error)); ;
|
||||
default: fmt::throw_exception("Unexpected error in reply to GetRoomMemberDataInternal: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
if (error_code != CELL_OK)
|
||||
|
@ -1081,7 +1082,7 @@ namespace np
|
|||
case rpcn::ErrorType::NotFound: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_STORE_NOT_FOUND); break;
|
||||
case rpcn::ErrorType::ScoreInvalid: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_INVALID_SCORE); break;
|
||||
case rpcn::ErrorType::ScoreHasData: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_GAME_DATA_ALREADY_EXISTS); break;
|
||||
default: fmt::throw_exception("Unexpected error in reply to RecordScoreData: %d", static_cast<u8>(error)); ;
|
||||
default: fmt::throw_exception("Unexpected error in reply to RecordScoreData: %d", static_cast<u8>(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1134,7 +1135,7 @@ namespace np
|
|||
{
|
||||
case rpcn::ErrorType::NoError: break;
|
||||
case rpcn::ErrorType::NotFound: score_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_GAME_DATA_MASTER_NOT_FOUND); return;
|
||||
default: fmt::throw_exception("Unexpected error in reply to GetScoreData: %d", static_cast<u8>(error)); ;
|
||||
default: fmt::throw_exception("Unexpected error in reply to GetScoreData: %d", static_cast<u8>(error));
|
||||
}
|
||||
|
||||
auto* tdata = std::get_if<tdata_get_score_data>(&score_trans->tdata);
|
||||
|
|
|
@ -599,7 +599,11 @@ namespace rpcn
|
|||
duration = std::min(duration, duration_ipv6);
|
||||
}
|
||||
|
||||
sem_rpcn.try_acquire_for(duration);
|
||||
// Expected to fail unless rpcn is terminated
|
||||
// The check is there to nuke a msvc warning
|
||||
if (!sem_rpcn.try_acquire_for(duration))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,33 +6,33 @@
|
|||
#include "Emu/RSX/RSXThread.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
|
||||
#include "xxhash.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace capture
|
||||
{
|
||||
void insert_mem_block_in_map(std::unordered_set<u64>& mem_changes, frame_capture_data::memory_block&& block, frame_capture_data::memory_block_data&& data)
|
||||
void insert_mem_block_in_map(u64& indexer, std::unordered_set<u64>& mem_changes, frame_capture_data::memory_block&& block, frame_capture_data::memory_block_data&& data)
|
||||
{
|
||||
if (!data.data.empty())
|
||||
{
|
||||
u64 data_hash = XXH64(data.data.data(), data.data.size(), 0);
|
||||
const auto [it, inserted] = frame_capture.memory_data_map.try_emplace(data, 0);
|
||||
u64& data_hash = it->second;
|
||||
|
||||
if (inserted)
|
||||
{
|
||||
data_hash = ++indexer;
|
||||
}
|
||||
|
||||
block.data_state = data_hash;
|
||||
|
||||
auto it = frame_capture.memory_data_map.find(data_hash);
|
||||
if (it != frame_capture.memory_data_map.end())
|
||||
{
|
||||
if (it->second.data != data.data)
|
||||
// screw this
|
||||
fmt::throw_exception("Memory map hash collision detected...cant capture");
|
||||
}
|
||||
else
|
||||
frame_capture.memory_data_map.insert(std::make_pair(data_hash, std::move(data)));
|
||||
const auto [block_it, inserted_block] = frame_capture.memory_map.try_emplace(block, 0);
|
||||
u64& block_hash = block_it->second;
|
||||
|
||||
if (inserted_block)
|
||||
{
|
||||
block_hash = ++indexer;
|
||||
}
|
||||
|
||||
u64 block_hash = XXH64(&block, sizeof(frame_capture_data::memory_block), 0);
|
||||
mem_changes.insert(block_hash);
|
||||
if (frame_capture.memory_map.find(block_hash) == frame_capture.memory_map.end())
|
||||
frame_capture.memory_map.insert(std::make_pair(block_hash, std::move(block)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ namespace rsx
|
|||
|
||||
// shove the mem_changes onto the last issued command
|
||||
std::unordered_set<u64>& mem_changes = frame_capture.replay_commands.back().memory_state;
|
||||
u64& mem_indexer = frame_capture.memory_indexer;
|
||||
|
||||
// capture fragment shader mem
|
||||
const auto [program_offset, program_location] = method_registers.shader_program_address();
|
||||
|
@ -63,7 +64,7 @@ namespace rsx
|
|||
frame_capture_data::memory_block_data block_data;
|
||||
block_data.data.resize(ucode_size + program_start);
|
||||
std::memcpy(block_data.data.data(), vm::base(addr), ucode_size + program_start);
|
||||
insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
|
||||
insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
|
||||
|
||||
// vertex shader is passed in registers, so it can be ignored
|
||||
|
||||
|
@ -90,7 +91,7 @@ namespace rsx
|
|||
frame_capture_data::memory_block_data block_data;
|
||||
block_data.data.resize(texSize);
|
||||
std::memcpy(block_data.data.data(), vm::base(texaddr), texSize);
|
||||
insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
|
||||
insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
|
||||
}
|
||||
|
||||
// save vertex texture mem
|
||||
|
@ -116,7 +117,7 @@ namespace rsx
|
|||
frame_capture_data::memory_block_data block_data;
|
||||
block_data.data.resize(texSize);
|
||||
std::memcpy(block_data.data.data(), vm::base(texaddr), texSize);
|
||||
insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
|
||||
insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
|
||||
}
|
||||
|
||||
// save vertex buffer memory
|
||||
|
@ -154,7 +155,7 @@ namespace rsx
|
|||
frame_capture_data::memory_block_data block_data;
|
||||
block_data.data.resize(bufferSize);
|
||||
std::memcpy(block_data.data.data(), vm::base(addr + (range.first * vertStride)), bufferSize);
|
||||
insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
|
||||
insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
|
||||
}
|
||||
while (method_registers.current_draw_clause.next());
|
||||
}
|
||||
|
@ -193,7 +194,7 @@ namespace rsx
|
|||
frame_capture_data::memory_block_data block_data;
|
||||
block_data.data.resize(bufferSize);
|
||||
std::memcpy(block_data.data.data(), vm::base(idxAddr), bufferSize);
|
||||
insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
|
||||
insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
|
||||
|
||||
switch (index_type)
|
||||
{
|
||||
|
@ -256,7 +257,7 @@ namespace rsx
|
|||
frame_capture_data::memory_block_data block_data;
|
||||
block_data.data.resize(bufferSize);
|
||||
std::memcpy(block_data.data.data(), vm::base(addr + (min_index * vertStride)), bufferSize);
|
||||
insert_mem_block_in_map(mem_changes, std::move(block), std::move(block_data));
|
||||
insert_mem_block_in_map(mem_indexer, mem_changes, std::move(block), std::move(block_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,7 +309,7 @@ namespace rsx
|
|||
frame_capture_data::memory_block_data block_data;
|
||||
block_data.data.resize(src_size);
|
||||
std::memcpy(block_data.data.data(), pixels_src, src_size);
|
||||
insert_mem_block_in_map(replay_command.memory_state, std::move(block), std::move(block_data));
|
||||
insert_mem_block_in_map(frame_capture.memory_indexer, replay_command.memory_state, std::move(block), std::move(block_data));
|
||||
|
||||
capture_display_tile_state(rsx, replay_command);
|
||||
}
|
||||
|
@ -340,14 +341,17 @@ namespace rsx
|
|||
src += in_pitch;
|
||||
}
|
||||
|
||||
insert_mem_block_in_map(replay_command.memory_state, std::move(block), std::move(block_data));
|
||||
insert_mem_block_in_map(frame_capture.memory_indexer, replay_command.memory_state, std::move(block), std::move(block_data));
|
||||
capture_display_tile_state(rsx, replay_command);
|
||||
}
|
||||
|
||||
void capture_display_tile_state(thread* rsx, frame_capture_data::replay_command& replay_command)
|
||||
{
|
||||
u64& mem_indexer = frame_capture.memory_indexer;
|
||||
|
||||
frame_capture_data::display_buffers_state dbstate;
|
||||
dbstate.count = rsx->display_buffers_count;
|
||||
|
||||
// should this only happen on flip?
|
||||
for (u32 i = 0; i < rsx->display_buffers_count; ++i)
|
||||
{
|
||||
|
@ -358,9 +362,13 @@ namespace rsx
|
|||
dbstate.buffers[i].pitch = db.pitch;
|
||||
}
|
||||
|
||||
const u64 dbnum = XXH64(&dbstate, sizeof(frame_capture_data::display_buffers_state), 0);
|
||||
if (frame_capture.display_buffers_map.find(dbnum) == frame_capture.display_buffers_map.end())
|
||||
frame_capture.display_buffers_map.insert(std::make_pair(dbnum, std::move(dbstate)));
|
||||
const auto [db_it, db_inserted] = frame_capture.display_buffers_map.try_emplace(dbstate, 0);
|
||||
u64& dbnum = db_it->second;
|
||||
|
||||
if (db_inserted)
|
||||
{
|
||||
dbnum = ++mem_indexer;
|
||||
}
|
||||
|
||||
// todo: hook tile call sys_rsx call or something
|
||||
frame_capture_data::tile_state tilestate;
|
||||
|
@ -386,10 +394,13 @@ namespace rsx
|
|||
zcstate.status1 = rsx->zculls[i].bound ? u32{zc.status1} : 0;
|
||||
}
|
||||
|
||||
const u64 tsnum = XXH64(&tilestate, sizeof(frame_capture_data::tile_state), 0);
|
||||
const auto [ts_it, ts_inserted] = frame_capture.tile_map.try_emplace(tilestate, 0);
|
||||
u64& tsnum = ts_it->second;
|
||||
|
||||
if (frame_capture.tile_map.find(tsnum) == frame_capture.tile_map.end())
|
||||
frame_capture.tile_map.insert(std::make_pair(tsnum, std::move(tilestate)));
|
||||
if (ts_inserted)
|
||||
{
|
||||
tsnum = ++mem_indexer;
|
||||
}
|
||||
|
||||
replay_command.display_buffer_state = dbnum;
|
||||
replay_command.tile_state = tsnum;
|
||||
|
|
|
@ -106,26 +106,26 @@ namespace rsx
|
|||
// apply memory needed for command
|
||||
for (const auto& state : replay_cmd.memory_state)
|
||||
{
|
||||
auto it = frame->memory_map.find(state);
|
||||
auto it = std::find_if(frame->memory_map.begin(), frame->memory_map.end(), FN(x.second == state));
|
||||
if (it == frame->memory_map.end())
|
||||
fmt::throw_exception("requested memory state for command not found in memory_map");
|
||||
|
||||
const auto& memblock = it->second;
|
||||
auto it_data = frame->memory_data_map.find(it->second.data_state);
|
||||
const auto& memblock = it->first;
|
||||
auto it_data = std::find_if(frame->memory_data_map.begin(), frame->memory_data_map.end(), FN(x.second == memblock.data_state));
|
||||
if (it_data == frame->memory_data_map.end())
|
||||
fmt::throw_exception("requested memory data state for command not found in memory_data_map");
|
||||
|
||||
const auto& data_block = it_data->second;
|
||||
const auto& data_block = it_data->first;
|
||||
std::memcpy(vm::base(get_address(memblock.offset, memblock.location)), data_block.data.data(), data_block.data.size());
|
||||
}
|
||||
|
||||
if (replay_cmd.display_buffer_state != 0 && replay_cmd.display_buffer_state != cs.display_buffer_hash)
|
||||
{
|
||||
auto it = frame->display_buffers_map.find(replay_cmd.display_buffer_state);
|
||||
auto it = std::find_if(frame->display_buffers_map.begin(), frame->display_buffers_map.end(), FN(x.second == replay_cmd.display_buffer_state));
|
||||
if (it == frame->display_buffers_map.end())
|
||||
fmt::throw_exception("requested display buffer for command not found");
|
||||
|
||||
const auto& dbstate = it->second;
|
||||
const auto& dbstate = it->first;
|
||||
for (u32 i = 0; i < dbstate.count; ++i)
|
||||
{
|
||||
const auto& buf = dbstate.buffers[i];
|
||||
|
@ -136,16 +136,17 @@ namespace rsx
|
|||
sys_rsx_context_attribute(context_id, 0x104, i,
|
||||
u64{dbstate.buffers[i].width} << 32 | dbstate.buffers[i].height, u64{dbstate.buffers[i].pitch} << 32 | dbstate.buffers[i].offset, 0);
|
||||
}
|
||||
|
||||
cs.display_buffer_hash = replay_cmd.display_buffer_state;
|
||||
}
|
||||
|
||||
if (replay_cmd.tile_state != 0 && replay_cmd.tile_state != cs.tile_hash)
|
||||
{
|
||||
auto it = frame->tile_map.find(replay_cmd.tile_state);
|
||||
auto it = std::find_if(frame->tile_map.begin(), frame->tile_map.end(), FN(x.second == replay_cmd.tile_state));
|
||||
if (it == frame->tile_map.end())
|
||||
fmt::throw_exception("requested tile state command not found");
|
||||
|
||||
const auto& tstate = it->second;
|
||||
const auto& tstate = it->first;
|
||||
for (u32 i = 0; i < limits::tiles_count; ++i)
|
||||
{
|
||||
const auto& ti = tstate.tiles[i];
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace rsx
|
|||
enum : u32
|
||||
{
|
||||
c_fc_magic = "RRC"_u32,
|
||||
c_fc_version = 0x5,
|
||||
c_fc_version = 0x6,
|
||||
};
|
||||
|
||||
struct frame_capture_data
|
||||
|
@ -92,19 +92,60 @@ namespace rsx
|
|||
u32 version = c_fc_version;
|
||||
u32 LE_format = std::endian::little == std::endian::native;
|
||||
|
||||
// hashmap of holding various states for tile
|
||||
std::unordered_map<u64, tile_state> tile_map;
|
||||
// hashmap of various memory 'changes' that can be applied to ps3 memory
|
||||
std::unordered_map<u64, memory_block> memory_map;
|
||||
// hashmap of memory blocks that can be applied, this is split from above for size decrease
|
||||
std::unordered_map<u64, memory_block_data> memory_data_map;
|
||||
// display buffer state map
|
||||
std::unordered_map<u64, display_buffers_state> display_buffers_map;
|
||||
// actual command queue to hold everything above
|
||||
struct bitwise_hasher
|
||||
{
|
||||
template <typename T>
|
||||
usz operator()(const T& key) const noexcept
|
||||
{
|
||||
if constexpr (!!(requires (const T& a) { a.data[0]; }))
|
||||
{
|
||||
return std::hash<std::string_view>{}(std::string_view{ reinterpret_cast<const char*>(key.data.data()), key.data.size() * sizeof(key.data[0]) });
|
||||
}
|
||||
|
||||
return std::hash<std::string_view>{}(std::string_view{ reinterpret_cast<const char*>(&key), sizeof(key) });
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator()(const T& keya, const T& keyb) const noexcept
|
||||
{
|
||||
if constexpr (!!(requires (const T& a) { a.data[0]; }))
|
||||
{
|
||||
if (keya.data.size() != keyb.data.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::equal(keya.data.begin(), keya.data.end(), keyb.data.begin());
|
||||
}
|
||||
|
||||
return std::equal(reinterpret_cast<const char*>(&keya), reinterpret_cast<const char*>(&keya) + sizeof(T), reinterpret_cast<const char*>(&keyb));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename V>
|
||||
using uno_bit_map = std::unordered_map<T, V, bitwise_hasher, bitwise_hasher>;
|
||||
|
||||
// Hashmap of holding various states for tile
|
||||
uno_bit_map<tile_state, u64> tile_map;
|
||||
|
||||
// Hashmap of various memory 'changes' that can be applied to ps3 memory
|
||||
uno_bit_map<memory_block, u64> memory_map;
|
||||
|
||||
// Hashmap of memory blocks that can be applied, this is split from above for size decrease
|
||||
uno_bit_map<memory_block_data, u64> memory_data_map;
|
||||
|
||||
// Display buffer state map
|
||||
uno_bit_map<display_buffers_state, u64> display_buffers_map;
|
||||
|
||||
// Actual command queue to hold everything above
|
||||
std::vector<replay_command> replay_commands;
|
||||
|
||||
// Initial registers state at the beginning of the capture
|
||||
rsx::rsx_state reg_state;
|
||||
|
||||
// Indexer for memory blocks
|
||||
u64 memory_indexer = 0x1234;
|
||||
|
||||
void reset()
|
||||
{
|
||||
magic = c_fc_magic;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "TextureUtils.h"
|
||||
#include "../RSXThread.h"
|
||||
#include "../rsx_utils.h"
|
||||
#include "3rdparty/bcdec/bcdec.hpp"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
|
@ -497,6 +498,63 @@ struct copy_rgb655_block_swizzled
|
|||
}
|
||||
};
|
||||
|
||||
struct copy_decoded_bc1_block
|
||||
{
|
||||
static void copy_mipmap_level(std::span<u32> dst, std::span<const u64> src, u16 width_in_block, u16 row_count, u16 depth, u32 dst_pitch_in_block, u32 src_pitch_in_block)
|
||||
{
|
||||
u32 src_offset = 0, dst_offset = 0, destinationPitch = dst_pitch_in_block * 4;
|
||||
for (u32 row = 0; row < row_count * depth; row++)
|
||||
{
|
||||
for (u32 col = 0; col < width_in_block; col++) {
|
||||
const u8* compressedBlock = reinterpret_cast<const u8*>(&src[src_offset + col]);
|
||||
u8* decompressedBlock = reinterpret_cast<u8*>(&dst[dst_offset + col * 4]);
|
||||
bcdec_bc1(compressedBlock, decompressedBlock, destinationPitch);
|
||||
}
|
||||
|
||||
src_offset += src_pitch_in_block;
|
||||
dst_offset += destinationPitch;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct copy_decoded_bc2_block
|
||||
{
|
||||
static void copy_mipmap_level(std::span<u32> dst, std::span<const u128> src, u16 width_in_block, u16 row_count, u16 depth, u32 dst_pitch_in_block, u32 src_pitch_in_block)
|
||||
{
|
||||
u32 src_offset = 0, dst_offset = 0, destinationPitch = dst_pitch_in_block * 4;
|
||||
for (u32 row = 0; row < row_count * depth; row++)
|
||||
{
|
||||
for (u32 col = 0; col < width_in_block; col++) {
|
||||
const u8* compressedBlock = reinterpret_cast<const u8*>(&src[src_offset + col]);
|
||||
u8* decompressedBlock = reinterpret_cast<u8*>(&dst[dst_offset + col * 4]);
|
||||
bcdec_bc2(compressedBlock, decompressedBlock, destinationPitch);
|
||||
}
|
||||
|
||||
src_offset += src_pitch_in_block;
|
||||
dst_offset += destinationPitch;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct copy_decoded_bc3_block
|
||||
{
|
||||
static void copy_mipmap_level(std::span<u32> dst, std::span<const u128> src, u16 width_in_block, u16 row_count, u16 depth, u32 dst_pitch_in_block, u32 src_pitch_in_block)
|
||||
{
|
||||
u32 src_offset = 0, dst_offset = 0, destinationPitch = dst_pitch_in_block * 4;
|
||||
for (u32 row = 0; row < row_count * depth; row++)
|
||||
{
|
||||
for (u32 col = 0; col < width_in_block; col++) {
|
||||
const u8* compressedBlock = reinterpret_cast<const u8*>(&src[src_offset + col]);
|
||||
u8* decompressedBlock = reinterpret_cast<u8*>(&dst[dst_offset + col * 4]);
|
||||
bcdec_bc3(compressedBlock, decompressedBlock, destinationPitch);
|
||||
}
|
||||
|
||||
src_offset += src_pitch_in_block;
|
||||
dst_offset += destinationPitch;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
|
@ -952,6 +1010,12 @@ namespace rsx
|
|||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||
{
|
||||
if (!caps.supports_dxt)
|
||||
{
|
||||
copy_decoded_bc1_block::copy_mipmap_level(dst_buffer.as_span<u32>(), src_layout.data.as_span<const u64>(), w, h, depth, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block);
|
||||
break;
|
||||
}
|
||||
|
||||
const bool is_3d = depth > 1;
|
||||
const bool is_po2 = utils::is_power_of_2(src_layout.width_in_texel) && utils::is_power_of_2(src_layout.height_in_texel);
|
||||
|
||||
|
@ -981,8 +1045,22 @@ namespace rsx
|
|||
}
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||
{
|
||||
if (!caps.supports_dxt)
|
||||
{
|
||||
copy_decoded_bc2_block::copy_mipmap_level(dst_buffer.as_span<u32>(), src_layout.data.as_span<const u128>(), w, h, depth, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block);
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||
{
|
||||
if (!caps.supports_dxt)
|
||||
{
|
||||
copy_decoded_bc3_block::copy_mipmap_level(dst_buffer.as_span<u32>(), src_layout.data.as_span<const u128>(), w, h, depth, get_row_pitch_in_block<u32>(w, caps.alignment), src_layout.pitch_in_block);
|
||||
break;
|
||||
}
|
||||
|
||||
const bool is_3d = depth > 1;
|
||||
const bool is_po2 = utils::is_power_of_2(src_layout.width_in_texel) && utils::is_power_of_2(src_layout.height_in_texel);
|
||||
|
||||
|
@ -1094,7 +1172,7 @@ namespace rsx
|
|||
return result;
|
||||
}
|
||||
|
||||
bool is_compressed_host_format(u32 texture_format)
|
||||
bool is_compressed_host_format(const texture_uploader_capabilities& caps, u32 texture_format)
|
||||
{
|
||||
switch (texture_format)
|
||||
{
|
||||
|
@ -1129,7 +1207,7 @@ namespace rsx
|
|||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||
return true;
|
||||
return caps.supports_dxt;
|
||||
}
|
||||
fmt::throw_exception("Unknown format 0x%x", texture_format);
|
||||
}
|
||||
|
|
|
@ -227,6 +227,7 @@ namespace rsx
|
|||
bool supports_vtc_decoding;
|
||||
bool supports_hw_deswizzle;
|
||||
bool supports_zero_copy;
|
||||
bool supports_dxt;
|
||||
usz alignment;
|
||||
};
|
||||
|
||||
|
@ -252,7 +253,7 @@ namespace rsx
|
|||
u8 get_format_block_size_in_bytes(rsx::surface_color_format format);
|
||||
u8 get_format_block_size_in_bytes(rsx::surface_depth_format2 format);
|
||||
|
||||
bool is_compressed_host_format(u32 format); // Returns true for host-compressed formats (DXT)
|
||||
bool is_compressed_host_format(const texture_uploader_capabilities& caps, u32 format); // Returns true for host-compressed formats (DXT)
|
||||
u8 get_format_sample_count(rsx::surface_antialiasing antialias);
|
||||
u32 get_max_depth_value(rsx::surface_depth_format2 format);
|
||||
bool is_depth_stencil_format(rsx::surface_depth_format2 format);
|
||||
|
|
|
@ -70,6 +70,7 @@ namespace gl
|
|||
|
||||
GLenum get_sized_internal_format(u32 texture_format)
|
||||
{
|
||||
const bool supports_dxt = get_driver_caps().EXT_texture_compression_s3tc_supported;
|
||||
switch (texture_format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_B8: return GL_R8;
|
||||
|
@ -92,9 +93,9 @@ namespace gl
|
|||
case CELL_GCM_TEXTURE_D1R5G5B5: return GL_BGR5_A1;
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8: return GL_BGRA8;
|
||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: return GL_RG16F;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return supports_dxt ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT : GL_BGRA8;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return supports_dxt ? GL_COMPRESSED_RGBA_S3TC_DXT3_EXT : GL_BGRA8;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return supports_dxt ? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_BGRA8;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: return GL_RG8;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: return GL_RG8_SNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return GL_BGRA8;
|
||||
|
@ -105,6 +106,7 @@ namespace gl
|
|||
|
||||
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format)
|
||||
{
|
||||
const bool supports_dxt = get_driver_caps().EXT_texture_compression_s3tc_supported;
|
||||
switch (texture_format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_B8: return std::make_tuple(GL_RED, GL_UNSIGNED_BYTE);
|
||||
|
@ -127,9 +129,9 @@ namespace gl
|
|||
case CELL_GCM_TEXTURE_D1R5G5B5: return std::make_tuple(GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV);
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8: return std::make_tuple(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
|
||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: return std::make_tuple(GL_RG, GL_HALF_FLOAT);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return std::make_tuple(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return std::make_tuple(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return std::make_tuple(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return std::make_tuple(supports_dxt ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT : GL_BGRA, GL_UNSIGNED_BYTE);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return std::make_tuple(supports_dxt ? GL_COMPRESSED_RGBA_S3TC_DXT3_EXT : GL_BGRA, GL_UNSIGNED_BYTE);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return std::make_tuple(supports_dxt ? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_BGRA, GL_UNSIGNED_BYTE);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: return std::make_tuple(GL_RG, GL_UNSIGNED_BYTE);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: return std::make_tuple(GL_RG, GL_BYTE);
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return std::make_tuple(GL_BGRA, GL_UNSIGNED_BYTE);
|
||||
|
@ -587,6 +589,7 @@ namespace gl
|
|||
.supports_vtc_decoding = false,
|
||||
.supports_hw_deswizzle = driver_caps.ARB_compute_shader_supported,
|
||||
.supports_zero_copy = false,
|
||||
.supports_dxt = driver_caps.EXT_texture_compression_s3tc_supported,
|
||||
.alignment = 4
|
||||
};
|
||||
|
||||
|
@ -596,7 +599,7 @@ namespace gl
|
|||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, GL_NONE);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, GL_NONE);
|
||||
|
||||
if (rsx::is_compressed_host_format(format)) [[likely]]
|
||||
if (rsx::is_compressed_host_format(caps, format)) [[likely]]
|
||||
{
|
||||
caps.supports_vtc_decoding = driver_caps.vendor_NVIDIA;
|
||||
unpack_settings.apply();
|
||||
|
@ -687,13 +690,13 @@ namespace gl
|
|||
if (driver_caps.ARB_compute_shader_supported)
|
||||
{
|
||||
u64 row_pitch = rsx::align2<u64, u64>(layout.width_in_block * block_size_in_bytes, caps.alignment);
|
||||
if (!rsx::is_compressed_host_format(format))
|
||||
{
|
||||
// Handle emulated compressed formats with host unpack (R8G8 compressed)
|
||||
row_pitch = std::max<u64>(row_pitch, dst->pitch());
|
||||
}
|
||||
|
||||
image_linear_size = row_pitch * layout.height_in_block * layout.depth;
|
||||
// We're in the "else" branch, so "is_compressed_host_format()" is always false.
|
||||
// Handle emulated compressed formats with host unpack (R8G8 compressed)
|
||||
row_pitch = std::max<u64>(row_pitch, dst->pitch());
|
||||
|
||||
// FIXME: Double-check this logic; it seems like we should always use texels both here and for row_pitch.
|
||||
image_linear_size = row_pitch * layout.height_in_texel * layout.depth;
|
||||
|
||||
compute_scratch_mem = { nullptr, g_compute_decode_buffer.alloc(static_cast<u32>(image_linear_size), 256) };
|
||||
compute_scratch_mem.first = reinterpret_cast<void*>(static_cast<uintptr_t>(compute_scratch_mem.second));
|
||||
|
@ -815,7 +818,8 @@ namespace gl
|
|||
// Calculate staging buffer size
|
||||
rsx::simple_array<std::byte> data_upload_buf;
|
||||
|
||||
if (rsx::is_compressed_host_format(gcm_format))
|
||||
rsx::texture_uploader_capabilities caps { .supports_dxt = gl::get_driver_caps().EXT_texture_compression_s3tc_supported };
|
||||
if (rsx::is_compressed_host_format(caps, gcm_format))
|
||||
{
|
||||
const auto& desc = subresources_layout[0];
|
||||
const u32 texture_data_sz = desc.width_in_block * desc.height_in_block * desc.depth * rsx::get_format_block_size_in_bytes(gcm_format);
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace gl
|
|||
|
||||
void capabilities::initialize()
|
||||
{
|
||||
int find_count = 18;
|
||||
int find_count = 19;
|
||||
int ext_count = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count);
|
||||
|
||||
|
@ -178,6 +178,13 @@ namespace gl
|
|||
find_count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (check(ext_name, "GL_EXT_texture_compression_s3tc"))
|
||||
{
|
||||
EXT_texture_compression_s3tc_supported = true;
|
||||
find_count--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Set GLSL version
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace gl
|
|||
bool NV_depth_buffer_float_supported = false;
|
||||
bool NV_fragment_shader_barycentric_supported = false;
|
||||
bool ARB_shader_texture_image_samples = false;
|
||||
bool EXT_texture_compression_s3tc_supported = false;
|
||||
|
||||
bool vendor_INTEL = false; // has broken GLSL compiler
|
||||
bool vendor_AMD = false; // has broken ARB_multidraw
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace vk
|
|||
case vk::driver_vendor::LAVAPIPE:
|
||||
case vk::driver_vendor::V3DV:
|
||||
case vk::driver_vendor::PANVK:
|
||||
case vk::driver_vendor::ARM_MALI:
|
||||
// TODO: Actually bench this. Using 32 for now to match other common configurations.
|
||||
case vk::driver_vendor::DOZEN:
|
||||
// Actual optimal size depends on the D3D device. Use 32 since it should work well on both AMD and NVIDIA
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
#include "VKFormats.h"
|
||||
#include "VKHelpers.h"
|
||||
#include "vkutils/device.h"
|
||||
#include "vkutils/image.h"
|
||||
|
||||
|
@ -193,6 +194,7 @@ namespace vk
|
|||
|
||||
VkFormat get_compatible_sampler_format(const gpu_formats_support& support, u32 format)
|
||||
{
|
||||
const bool supports_dxt = vk::get_current_renderer()->get_texture_compression_bc_support();
|
||||
switch (format)
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
|
@ -213,9 +215,9 @@ namespace vk
|
|||
#endif
|
||||
case CELL_GCM_TEXTURE_B8: return VK_FORMAT_R8_UNORM;
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8: return VK_FORMAT_B8G8R8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return VK_FORMAT_BC2_UNORM_BLOCK;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return supports_dxt ? VK_FORMAT_BC1_RGBA_UNORM_BLOCK : VK_FORMAT_B8G8R8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return supports_dxt ? VK_FORMAT_BC2_UNORM_BLOCK : VK_FORMAT_B8G8R8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return supports_dxt ? VK_FORMAT_BC3_UNORM_BLOCK : VK_FORMAT_B8G8R8A8_UNORM;
|
||||
case CELL_GCM_TEXTURE_G8B8: return VK_FORMAT_R8G8_UNORM;
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8: return support.d24_unorm_s8? VK_FORMAT_D24_UNORM_S8_UINT : VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
|
|
|
@ -145,6 +145,9 @@ namespace vk
|
|||
case driver_vendor::PANVK:
|
||||
// Needs more testing
|
||||
break;
|
||||
case driver_vendor::ARM_MALI:
|
||||
// Needs more testing
|
||||
break;
|
||||
default:
|
||||
rsx_log.warning("Unsupported device: %s", gpu_name);
|
||||
}
|
||||
|
|
|
@ -188,6 +188,7 @@ namespace vk
|
|||
case driver_vendor::V3DV:
|
||||
case driver_vendor::HONEYKRISP:
|
||||
case driver_vendor::PANVK:
|
||||
case driver_vendor::ARM_MALI:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -929,7 +929,7 @@ namespace vk
|
|||
return *pcmd;
|
||||
}
|
||||
|
||||
static const std::pair<u32, u32> calculate_upload_pitch(int format, u32 heap_align, vk::image* dst_image, const rsx::subresource_layout& layout)
|
||||
static const std::pair<u32, u32> calculate_upload_pitch(int format, u32 heap_align, vk::image* dst_image, const rsx::subresource_layout& layout, const rsx::texture_uploader_capabilities& caps)
|
||||
{
|
||||
u32 block_in_pixel = rsx::get_format_block_size_in_texel(format);
|
||||
u8 block_size_in_bytes = rsx::get_format_block_size_in_bytes(format);
|
||||
|
@ -950,7 +950,7 @@ namespace vk
|
|||
|
||||
// We have row_pitch in source coordinates. But some formats have a software decode step which can affect this packing!
|
||||
// For such formats, the packed pitch on src does not match packed pitch on dst
|
||||
if (!rsx::is_compressed_host_format(format))
|
||||
if (!rsx::is_compressed_host_format(caps, format))
|
||||
{
|
||||
const auto host_texel_width = vk::get_format_texel_width(dst_image->format());
|
||||
const auto host_packed_pitch = host_texel_width * layout.width_in_texel;
|
||||
|
@ -977,7 +977,8 @@ namespace vk
|
|||
VkImageAspectFlags flags, vk::data_heap &upload_heap, u32 heap_align, rsx::flags32_t image_setup_flags)
|
||||
{
|
||||
const bool requires_depth_processing = (dst_image->aspect() & VK_IMAGE_ASPECT_STENCIL_BIT) || (format == CELL_GCM_TEXTURE_DEPTH16_FLOAT);
|
||||
rsx::texture_uploader_capabilities caps{ .alignment = heap_align };
|
||||
auto pdev = vk::get_current_renderer();
|
||||
rsx::texture_uploader_capabilities caps{ .supports_dxt = pdev->get_texture_compression_bc_support(), .alignment = heap_align };
|
||||
rsx::texture_memory_info opt{};
|
||||
bool check_caps = true;
|
||||
|
||||
|
@ -997,11 +998,11 @@ namespace vk
|
|||
|
||||
for (const rsx::subresource_layout &layout : subresource_layout)
|
||||
{
|
||||
const auto [row_pitch, upload_pitch_in_texel] = calculate_upload_pitch(format, heap_align, dst_image, layout);
|
||||
const auto [row_pitch, upload_pitch_in_texel] = calculate_upload_pitch(format, heap_align, dst_image, layout, caps);
|
||||
caps.alignment = row_pitch;
|
||||
|
||||
// Calculate estimated memory utilization for this subresource
|
||||
image_linear_size = row_pitch * layout.height_in_block * layout.depth;
|
||||
image_linear_size = row_pitch * layout.depth * (rsx::is_compressed_host_format(caps, format) ? layout.height_in_block : layout.height_in_texel);
|
||||
|
||||
// Only do GPU-side conversion if occupancy is good
|
||||
if (check_caps)
|
||||
|
|
|
@ -55,7 +55,8 @@ namespace vk
|
|||
NVK,
|
||||
V3DV,
|
||||
HONEYKRISP,
|
||||
PANVK
|
||||
PANVK,
|
||||
ARM_MALI
|
||||
};
|
||||
|
||||
driver_vendor get_driver_vendor();
|
||||
|
|
|
@ -134,6 +134,10 @@ namespace vk
|
|||
// So far only AMD is known to remap image view and border color together. Mark as not required.
|
||||
custom_border_color_support.require_border_color_remap = get_driver_vendor() != driver_vendor::AMD;
|
||||
}
|
||||
|
||||
// v3dv and PanVK support BC1-BC3 which is all we require, support is reported as false since not all formats are supported
|
||||
optional_features_support.texture_compression_bc = features.textureCompressionBC
|
||||
|| get_driver_vendor() == driver_vendor::V3DV || get_driver_vendor() == driver_vendor::PANVK;
|
||||
}
|
||||
|
||||
void physical_device::get_physical_device_properties(bool allow_extensions)
|
||||
|
@ -303,9 +307,13 @@ namespace vk
|
|||
}
|
||||
|
||||
if (gpu_name.find("Panfrost") != umax)
|
||||
{
|
||||
{ // e.g. "Mali-G610 (Panfrost)"
|
||||
return driver_vendor::PANVK;
|
||||
}
|
||||
else if (gpu_name.find("Mali") != umax)
|
||||
{ // e.g. "Mali-G610", hence "else"
|
||||
return driver_vendor::ARM_MALI;
|
||||
}
|
||||
|
||||
return driver_vendor::unknown;
|
||||
}
|
||||
|
@ -336,6 +344,8 @@ namespace vk
|
|||
return driver_vendor::HONEYKRISP;
|
||||
case VK_DRIVER_ID_MESA_PANVK:
|
||||
return driver_vendor::PANVK;
|
||||
case VK_DRIVER_ID_ARM_PROPRIETARY:
|
||||
return driver_vendor::ARM_MALI;
|
||||
default:
|
||||
// Mobile?
|
||||
return driver_vendor::unknown;
|
||||
|
@ -471,8 +481,7 @@ namespace vk
|
|||
// Enable hardware features manually
|
||||
// Currently we require:
|
||||
// 1. Anisotropic sampling
|
||||
// 2. DXT support
|
||||
// 3. Indexable storage buffers
|
||||
// 2. Indexable storage buffers
|
||||
VkPhysicalDeviceFeatures enabled_features{};
|
||||
if (pgpu->shader_types_support.allow_float16)
|
||||
{
|
||||
|
@ -566,7 +575,7 @@ namespace vk
|
|||
// enabled_features.shaderCullDistance = VK_TRUE; // Alt notation of clip distance
|
||||
|
||||
enabled_features.samplerAnisotropy = VK_TRUE;
|
||||
enabled_features.textureCompressionBC = VK_TRUE;
|
||||
enabled_features.textureCompressionBC = pgpu->optional_features_support.texture_compression_bc;
|
||||
enabled_features.shaderStorageBufferArrayDynamicIndexing = VK_TRUE;
|
||||
|
||||
// Optionally disable unsupported stuff
|
||||
|
@ -659,19 +668,6 @@ namespace vk
|
|||
enabled_features.logicOp = VK_FALSE;
|
||||
}
|
||||
|
||||
if (!pgpu->features.textureCompressionBC && pgpu->get_driver_vendor() == driver_vendor::V3DV)
|
||||
{
|
||||
// v3dv supports BC1-BC3 which is all we require, support is reported as false since not all formats are supported
|
||||
rsx_log.error("Your GPU running on the V3DV driver does not support full texture block compression. Graphics may not render correctly.");
|
||||
enabled_features.textureCompressionBC = VK_FALSE;
|
||||
}
|
||||
|
||||
if (!pgpu->features.textureCompressionBC && pgpu->get_driver_vendor() == driver_vendor::PANVK)
|
||||
{
|
||||
rsx_log.error("Your GPU running on the PANVK driver does not support full texture block compression. Graphics may not render correctly.");
|
||||
enabled_features.textureCompressionBC = VK_FALSE;
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo device = {};
|
||||
device.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
device.pNext = nullptr;
|
||||
|
|
|
@ -92,6 +92,7 @@ namespace vk
|
|||
bool synchronization_2 = false;
|
||||
bool unrestricted_depth_range = false;
|
||||
bool extended_device_fault = false;
|
||||
bool texture_compression_bc = false;
|
||||
} optional_features_support;
|
||||
|
||||
friend class render_device;
|
||||
|
@ -190,6 +191,7 @@ namespace vk
|
|||
bool get_barycoords_support() const { return pgpu->optional_features_support.barycentric_coords; }
|
||||
bool get_synchronization2_support() const { return pgpu->optional_features_support.synchronization_2; }
|
||||
bool get_extended_device_fault_support() const { return pgpu->optional_features_support.extended_device_fault; }
|
||||
bool get_texture_compression_bc_support() const { return pgpu->optional_features_support.texture_compression_bc; }
|
||||
|
||||
u64 get_descriptor_update_after_bind_support() const { return pgpu->descriptor_indexing_support.update_after_bind_mask; }
|
||||
u32 get_descriptor_max_draw_calls() const { return pgpu->descriptor_max_draw_calls; }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
namespace utils
|
||||
{
|
||||
template <typename T>
|
||||
concept FastRandomAccess = requires (T& obj)
|
||||
concept FastRandomAccess = requires (const T& obj)
|
||||
{
|
||||
std::data(obj)[std::size(obj)];
|
||||
};
|
||||
|
@ -24,13 +24,13 @@ namespace utils
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
concept TupleAlike = requires ()
|
||||
concept TupleAlike = (!FastRandomAccess<T>) && requires ()
|
||||
{
|
||||
std::tuple_size<std::remove_cv_t<T>>::value;
|
||||
std::tuple_size<std::remove_cvref_t<T>>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept ListAlike = requires (T& obj) { obj.insert(obj.end(), std::declval<typename T::value_type>()); };
|
||||
concept ListAlike = requires (std::remove_cvref_t<T>& obj) { obj.insert(obj.end(), std::declval<typename T::value_type>()); };
|
||||
|
||||
struct serial;
|
||||
|
||||
|
@ -249,6 +249,15 @@ public:
|
|||
return raw_serialize(std::addressof(obj), sizeof(obj));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr usz c_tup_size = std::tuple_size_v<std::conditional_t<TupleAlike<T>, std::remove_cvref_t<T>, std::tuple<>>>;
|
||||
|
||||
template <typename T>
|
||||
static std::remove_cvref_t<T>& as_nonconst(T&& arg) noexcept
|
||||
{
|
||||
return const_cast<std::remove_cvref_t<T>&>(static_cast<const T&>(arg));
|
||||
}
|
||||
|
||||
// std::vector, std::basic_string
|
||||
// Discourage using std::pair/tuple with vectors because it eliminates the possibility of bitwise optimization
|
||||
template <typename T> requires FastRandomAccess<T> && ListAlike<T> && (!TupleAlike<typename T::value_type>)
|
||||
|
@ -327,9 +336,24 @@ public:
|
|||
{
|
||||
for (auto&& value : obj)
|
||||
{
|
||||
if (!serialize(value))
|
||||
if constexpr (c_tup_size<decltype(*std::data(obj))> == 2)
|
||||
{
|
||||
return false;
|
||||
if (!serialize(as_nonconst(std::get<0>(value))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!serialize(as_nonconst(std::get<1>(value))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!serialize(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,9 +371,24 @@ public:
|
|||
|
||||
for (auto&& value : obj)
|
||||
{
|
||||
if (!serialize(value))
|
||||
if constexpr (c_tup_size<decltype(value)> == 2)
|
||||
{
|
||||
return false;
|
||||
if (!serialize(as_nonconst(std::get<0>(value))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!serialize(as_nonconst(std::get<1>(value))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!serialize(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +451,7 @@ public:
|
|||
}
|
||||
|
||||
// std::pair, std::tuple
|
||||
template <typename T> requires TupleAlike<T> && (!FastRandomAccess<T>)
|
||||
template <typename T> requires TupleAlike<T>
|
||||
bool serialize(T& obj)
|
||||
{
|
||||
return serialize_tuple(obj);
|
||||
|
@ -423,7 +462,7 @@ public:
|
|||
bool operator()(Args&&... args) noexcept
|
||||
{
|
||||
return ((AUDIT(!std::is_const_v<std::remove_reference_t<Args>> || is_writing())
|
||||
, serialize(const_cast<std::remove_cvref_t<Args>&>(static_cast<const Args&>(args)))), ...);
|
||||
, serialize(as_nonconst(args))), ...);
|
||||
}
|
||||
|
||||
// Code style utility, for when utils::serial is a pointer for example
|
||||
|
@ -519,30 +558,48 @@ public:
|
|||
AUDIT(!is_writing());
|
||||
|
||||
using type = std::remove_const_t<T>;
|
||||
using not_tuple_t = std::conditional_t<TupleAlike<T>, char, type>;
|
||||
|
||||
if constexpr (Bitcopy<T>)
|
||||
{
|
||||
u8 buf[sizeof(type)]{};
|
||||
u8 buf[sizeof(not_tuple_t)]{};
|
||||
ensure(raw_serialize(buf, sizeof(buf)));
|
||||
return std::bit_cast<type>(buf);
|
||||
}
|
||||
else if constexpr (std::is_constructible_v<type, stx::exact_t<serial&>>)
|
||||
{
|
||||
return type(stx::exact_t<serial&>(*this));
|
||||
}
|
||||
else if constexpr (std::is_constructible_v<type>)
|
||||
{
|
||||
type value{};
|
||||
ensure(serialize(value));
|
||||
return value;
|
||||
return std::bit_cast<not_tuple_t>(buf);
|
||||
}
|
||||
else if constexpr (TupleAlike<T>)
|
||||
{
|
||||
static_assert(std::tuple_size_v<type> == 2, "Unimplemented tuple serialization!");
|
||||
constexpr usz tup_size = c_tup_size<type>;
|
||||
|
||||
auto first = operator std::remove_cvref_t<decltype(std::get<0>(std::declval<type&>()))>();
|
||||
return type{ std::move(first)
|
||||
, operator std::remove_cvref_t<decltype(std::get<1>(std::declval<type&>()))> };
|
||||
static_assert(tup_size == 2 || tup_size == 4, "Unimplemented tuple serialization!");
|
||||
|
||||
using first_t = std::remove_cvref_t<decltype(std::get<std::min<usz>(0, tup_size - 1)>(std::declval<type&>()))>;
|
||||
using second_t = std::remove_cvref_t<decltype(std::get<std::min<usz>(1, tup_size - 1)>(std::declval<type&>()))>;
|
||||
using third_t = std::remove_cvref_t<decltype(std::get<std::min<usz>(2, tup_size - 1)>(std::declval<type&>()))>;
|
||||
using fourth_t = std::remove_cvref_t<decltype(std::get<std::min<usz>(3, tup_size - 1)>(std::declval<type&>()))>;
|
||||
|
||||
first_t first = this->operator first_t();
|
||||
|
||||
if constexpr (tup_size == 4)
|
||||
{
|
||||
second_t second = this->operator second_t();
|
||||
third_t third = this->operator third_t();
|
||||
|
||||
return type{ std::move(first), std::move(second), std::move(third), this->operator fourth_t() };
|
||||
}
|
||||
else
|
||||
{
|
||||
return type{ std::move(first), this->operator second_t() };
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_constructible_v<type, stx::exact_t<serial&>>)
|
||||
{
|
||||
return not_tuple_t(stx::exact_t<serial&>(*this));
|
||||
}
|
||||
else if constexpr (std::is_constructible_v<type>)
|
||||
{
|
||||
not_tuple_t value{};
|
||||
ensure(serialize(value));
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue