mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-01 18:40:57 -06:00
Merge branch 'shadps4-emu:main' into jane/buffer-gc-run
This commit is contained in:
commit
59dd371c53
4
.github/linux-appimage-sdl.sh
vendored
4
.github/linux-appimage-sdl.sh
vendored
@ -8,8 +8,8 @@ if [[ -z $GITHUB_WORKSPACE ]]; then
|
||||
fi
|
||||
|
||||
# Prepare Tools for building the AppImage
|
||||
wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||
wget -q https://github.com/linuxdeploy/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt-x86_64.sh
|
||||
wget --waitretry=3 --read-timeout=20 --timeout=15 --tries=5 -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||
wget --waitretry=3 --read-timeout=20 --timeout=15 --tries=5 -q https://github.com/linuxdeploy/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt-x86_64.sh
|
||||
|
||||
chmod a+x linuxdeploy-x86_64.AppImage
|
||||
chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh
|
||||
|
||||
@ -25,8 +25,8 @@ enum HideCursorState : int { Never, Idle, Always };
|
||||
|
||||
enum GpuReadbacksMode : int {
|
||||
Disabled,
|
||||
Low,
|
||||
High,
|
||||
Relaxed,
|
||||
Precise,
|
||||
};
|
||||
|
||||
void load(const std::filesystem::path& path, bool is_game_specific = false);
|
||||
|
||||
@ -276,7 +276,10 @@ int PS4_SYSV_ABI sceKernelRemoveExceptionHandler(s32 signum) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
int const native_signum = OrbisToNativeSignal(signum);
|
||||
ASSERT_MSG(Handlers[native_signum], "Invalid parameters");
|
||||
if (!Handlers[native_signum]) {
|
||||
LOG_WARNING(Lib_Kernel, "removing non-installed handler for signum {}", signum);
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
Handlers[native_signum] = nullptr;
|
||||
#ifndef _WIN64
|
||||
if (native_signum == SIGSEGV || native_signum == SIGBUS || native_signum == SIGILL) {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/network/ssl2.h"
|
||||
#include "core/libraries/network/ssl2_error.h"
|
||||
|
||||
namespace Libraries::Ssl2 {
|
||||
|
||||
@ -108,8 +109,13 @@ int PS4_SYSV_ABI sceSslEnableVerifyOption() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceSslFreeCaCerts() {
|
||||
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
|
||||
int PS4_SYSV_ABI sceSslFreeCaCerts(s32 ssl_ctx_id, OrbisSslCaCerts* certs) {
|
||||
LOG_ERROR(Lib_Ssl2, "(DUMMY) called");
|
||||
if (certs == nullptr) {
|
||||
return ORBIS_SSL_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
delete (certs->certs);
|
||||
// delete (certs->pool);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@ -128,17 +134,13 @@ int PS4_SYSV_ABI sceSslGetAlpnSelected() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
struct OrbisSslCaCerts {
|
||||
void* certs;
|
||||
u64 num;
|
||||
void* pool;
|
||||
};
|
||||
|
||||
int PS4_SYSV_ABI sceSslGetCaCerts(int sslCtxId, OrbisSslCaCerts* certs) {
|
||||
// check if it is same as libSceSsl
|
||||
int PS4_SYSV_ABI sceSslGetCaCerts(s32 ssl_ctx_id, OrbisSslCaCerts* certs) {
|
||||
LOG_ERROR(Lib_Ssl2, "(DUMMY) called");
|
||||
certs->certs = nullptr;
|
||||
certs->num = 0;
|
||||
if (certs == nullptr) {
|
||||
return ORBIS_SSL_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
certs->certs = new OrbisSslData{nullptr, 0};
|
||||
certs->num = 1;
|
||||
certs->pool = nullptr;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@ -10,5 +10,17 @@ class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::Ssl2 {
|
||||
|
||||
struct OrbisSslData {
|
||||
char* ptr;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
struct OrbisSslCaCerts {
|
||||
OrbisSslData* certs;
|
||||
u64 num;
|
||||
void* pool;
|
||||
};
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Ssl2
|
||||
8
src/core/libraries/network/ssl2_error.h
Normal file
8
src/core/libraries/network/ssl2_error.h
Normal file
@ -0,0 +1,8 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/libraries/error_codes.h"
|
||||
|
||||
constexpr int ORBIS_SSL_ERROR_INVALID_ARGUMENT = 0x8095F007;
|
||||
@ -333,6 +333,9 @@ static bool match(std::string_view str, std::string_view pattern) {
|
||||
for (auto str_wild_it = str_it; str_wild_it <= str.end(); ++str_wild_it) {
|
||||
if (match({str_wild_it, str.end()}, {pat_it + 1, pattern.end()})) {
|
||||
return true;
|
||||
} else if (str_wild_it == str.end()) {
|
||||
// Avoid incrementing str_wild_it past str.end().
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -458,6 +458,7 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) {
|
||||
IR::TextureInstInfo info{};
|
||||
info.has_lod.Assign(has_mip);
|
||||
info.is_array.Assign(mimg.da);
|
||||
info.is_r128.Assign(mimg.r128);
|
||||
|
||||
boost::container::static_vector<IR::F32, 4> comps;
|
||||
for (u32 i = 0; i < 4; i++) {
|
||||
|
||||
@ -86,6 +86,7 @@ struct ImageResource {
|
||||
} else {
|
||||
const auto raw = info.template ReadUdSharp<u128>(sharp_idx);
|
||||
std::memcpy(&image, &raw, sizeof(raw));
|
||||
image.pitch = image.width;
|
||||
}
|
||||
if (!image.Valid()) {
|
||||
LOG_DEBUG(Render_Vulkan, "Encountered invalid image sharp");
|
||||
|
||||
@ -95,7 +95,7 @@ public:
|
||||
}
|
||||
if constexpr (type == Type::CPU) {
|
||||
UpdateProtection<!enable, false>();
|
||||
} else if (Config::getReadbacksMode() == Config::GpuReadbacksMode::High) {
|
||||
} else if (Config::getReadbacksMode() == Config::GpuReadbacksMode::Precise) {
|
||||
UpdateProtection<enable, true>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,33 +461,36 @@ static std::pair<u32, u32> SanitizeCopyLayers(const ImageInfo& src_info, const I
|
||||
|
||||
void Image::CopyImage(Image& src_image) {
|
||||
const auto& src_info = src_image.info;
|
||||
|
||||
const u32 num_mips = std::min(src_info.resources.levels, info.resources.levels);
|
||||
|
||||
// Check format compatibility
|
||||
// Format mismatch warning (safe but useful)
|
||||
if (src_info.pixel_format != info.pixel_format) {
|
||||
LOG_DEBUG(Render_Vulkan,
|
||||
"Copy between different formats: src={}, dst={}. Color may be incorrect.",
|
||||
"Copy between different formats: src={}, dst={}. "
|
||||
"Result may be undefined.",
|
||||
vk::to_string(src_info.pixel_format), vk::to_string(info.pixel_format));
|
||||
}
|
||||
|
||||
const u32 width = src_info.size.width;
|
||||
const u32 height = src_info.size.height;
|
||||
const u32 base_width = src_info.size.width;
|
||||
const u32 base_height = src_info.size.height;
|
||||
const u32 base_depth =
|
||||
info.type == AmdGpu::ImageType::Color3D ? info.size.depth : src_info.size.depth;
|
||||
|
||||
auto [test_src_layers, test_dst_layers] = SanitizeCopyLayers(src_info, info, base_depth);
|
||||
|
||||
ASSERT(test_src_layers == test_dst_layers || num_mips == 1 ||
|
||||
(ConvertImageType(src_info.type) != ConvertImageType(info.type) &&
|
||||
(test_src_layers == 1 || test_dst_layers == 1)));
|
||||
|
||||
// Match sample count before copying
|
||||
SetBackingSamples(info.num_samples, false);
|
||||
src_image.SetBackingSamples(src_info.num_samples);
|
||||
|
||||
boost::container::small_vector<vk::ImageCopy, 8> image_copies;
|
||||
boost::container::small_vector<vk::ImageCopy, 8> regions;
|
||||
|
||||
const vk::ImageAspectFlags src_aspect =
|
||||
src_image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil;
|
||||
|
||||
const vk::ImageAspectFlags dst_aspect = aspect_mask & ~vk::ImageAspectFlagBits::eStencil;
|
||||
|
||||
const bool src_is_2d = ConvertImageType(src_info.type) == vk::ImageType::e2D;
|
||||
const bool src_is_3d = ConvertImageType(src_info.type) == vk::ImageType::e3D;
|
||||
|
||||
const bool dst_is_2d = ConvertImageType(info.type) == vk::ImageType::e2D;
|
||||
const bool dst_is_3d = ConvertImageType(info.type) == vk::ImageType::e3D;
|
||||
|
||||
@ -495,103 +498,68 @@ void Image::CopyImage(Image& src_image) {
|
||||
const bool is_3d_to_2d = src_is_3d && dst_is_2d;
|
||||
const bool is_same_type = !is_2d_to_3d && !is_3d_to_2d;
|
||||
|
||||
// Determine aspect mask - exclude stencil
|
||||
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor;
|
||||
|
||||
// For depth/stencil images, only copy the depth aspect (skip stencil)
|
||||
if (src_image.aspect_mask & vk::ImageAspectFlagBits::eDepth) {
|
||||
aspect = vk::ImageAspectFlagBits::eDepth;
|
||||
}
|
||||
|
||||
for (u32 mip = 0; mip < num_mips; ++mip) {
|
||||
const auto mip_w = std::max(width >> mip, 1u);
|
||||
const auto mip_h = std::max(height >> mip, 1u);
|
||||
const auto mip_d = std::max(base_depth >> mip, 1u);
|
||||
const u32 mip_w = std::max(base_width >> mip, 1u);
|
||||
const u32 mip_h = std::max(base_height >> mip, 1u);
|
||||
const u32 mip_d = std::max(base_depth >> mip, 1u);
|
||||
|
||||
auto [src_layers, dst_layers] = SanitizeCopyLayers(src_info, info, mip_d);
|
||||
|
||||
vk::ImageCopy region{};
|
||||
|
||||
region.srcSubresource.aspectMask = src_aspect;
|
||||
region.srcSubresource.mipLevel = mip;
|
||||
region.srcSubresource.baseArrayLayer = 0;
|
||||
|
||||
region.dstSubresource.aspectMask = dst_aspect;
|
||||
region.dstSubresource.mipLevel = mip;
|
||||
region.dstSubresource.baseArrayLayer = 0;
|
||||
|
||||
if (is_same_type) {
|
||||
u32 copy_layers = std::min(src_layers, dst_layers);
|
||||
|
||||
if (src_is_3d)
|
||||
src_layers = 1;
|
||||
if (dst_is_3d)
|
||||
dst_layers = 1;
|
||||
|
||||
vk::ImageCopy copy_region = {
|
||||
.srcSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = mip,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = copy_layers,
|
||||
},
|
||||
.dstSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = mip,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = copy_layers,
|
||||
},
|
||||
.extent = vk::Extent3D(mip_w, mip_h, mip_d),
|
||||
};
|
||||
image_copies.push_back(copy_region);
|
||||
// 2D->2D OR 3D->3D
|
||||
if (src_is_3d) {
|
||||
// 3D images must use layerCount=1
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.dstSubresource.layerCount = 1;
|
||||
region.extent = vk::Extent3D(mip_w, mip_h, mip_d);
|
||||
} else {
|
||||
// Array images
|
||||
const u32 copy_layers = std::min(src_layers, dst_layers);
|
||||
region.srcSubresource.layerCount = copy_layers;
|
||||
region.dstSubresource.layerCount = copy_layers;
|
||||
region.extent = vk::Extent3D(mip_w, mip_h, 1);
|
||||
}
|
||||
} else if (is_2d_to_3d) {
|
||||
vk::ImageCopy copy_region = {
|
||||
.srcSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = mip,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = src_layers,
|
||||
},
|
||||
.dstSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = mip,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.extent = vk::Extent3D(mip_w, mip_h, src_layers),
|
||||
};
|
||||
image_copies.push_back(copy_region);
|
||||
// 2D array -> 3D volume
|
||||
region.srcSubresource.layerCount = src_layers;
|
||||
region.dstSubresource.layerCount = 1;
|
||||
region.extent = vk::Extent3D(mip_w, mip_h, src_layers);
|
||||
} else if (is_3d_to_2d) {
|
||||
vk::ImageCopy copy_region = {
|
||||
.srcSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = mip,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.dstSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = mip,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = dst_layers,
|
||||
},
|
||||
.extent = vk::Extent3D(mip_w, mip_h, dst_layers),
|
||||
};
|
||||
image_copies.push_back(copy_region);
|
||||
// 3D volume -> 2D array
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.dstSubresource.layerCount = dst_layers;
|
||||
region.extent = vk::Extent3D(mip_w, mip_h, dst_layers);
|
||||
}
|
||||
|
||||
regions.push_back(region);
|
||||
}
|
||||
|
||||
scheduler->EndRendering();
|
||||
|
||||
// Remove the pipeline stage flags - they don't belong here
|
||||
src_image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {});
|
||||
|
||||
Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, {});
|
||||
|
||||
auto cmdbuf = scheduler->CommandBuffer();
|
||||
|
||||
if (!image_copies.empty()) {
|
||||
cmdbuf.copyImage(src_image.GetImage(), vk::ImageLayout::eTransferSrcOptimal, GetImage(),
|
||||
vk::ImageLayout::eTransferDstOptimal, image_copies);
|
||||
if (!regions.empty()) {
|
||||
cmdbuf.copyImage(src_image.GetImage(), src_image.backing->state.layout, GetImage(),
|
||||
backing->state.layout, regions);
|
||||
}
|
||||
|
||||
// Remove pipeline stage flags here too
|
||||
src_image.Transit(vk::ImageLayout::eShaderReadOnlyOptimal, vk::AccessFlagBits2::eShaderRead,
|
||||
{});
|
||||
|
||||
Transit(vk::ImageLayout::eShaderReadOnlyOptimal, vk::AccessFlagBits2::eShaderRead, {});
|
||||
Transit(vk::ImageLayout::eGeneral,
|
||||
vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eTransferRead, {});
|
||||
}
|
||||
|
||||
void Image::CopyImageWithBuffer(Image& src_image, vk::Buffer buffer, u64 offset) {
|
||||
const auto& src_info = src_image.info;
|
||||
const u32 num_mips = std::min(src_info.resources.levels, info.resources.levels);
|
||||
|
||||
@ -48,7 +48,7 @@ struct ImageInfo {
|
||||
}
|
||||
Extent2D BlockDim() const {
|
||||
const auto dim = props.is_block ? 2 : 0;
|
||||
return Extent2D{size.width >> dim, size.height >> dim};
|
||||
return Extent2D{pitch >> dim, size.height >> dim};
|
||||
}
|
||||
|
||||
s32 MipOf(const ImageInfo& info) const;
|
||||
|
||||
@ -297,14 +297,6 @@ std::tuple<ImageId, int, int> TextureCache::ResolveOverlap(const ImageInfo& imag
|
||||
if (image_info.guest_address == cache_image.info.guest_address) {
|
||||
const u32 lhs_block_size = image_info.num_bits * image_info.num_samples;
|
||||
const u32 rhs_block_size = cache_image.info.num_bits * cache_image.info.num_samples;
|
||||
|
||||
if (image_info.pitch != cache_image.info.pitch) {
|
||||
if (safe_to_delete) {
|
||||
FreeImage(cache_image_id);
|
||||
}
|
||||
return {merged_image_id, -1, -1};
|
||||
}
|
||||
|
||||
if (image_info.BlockDim() != cache_image.info.BlockDim() ||
|
||||
lhs_block_size != rhs_block_size) {
|
||||
// Very likely this kind of overlap is caused by allocation from a pool.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user