mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-18 17:34:52 +00:00
texture_cache: Improve support for stencil reads (#1758)
* texture_cache: Improve support for stencil reads * libraries: Supress some spammy logs * core: Support loading font libraries * texture_cache: Remove assert
This commit is contained in:
parent
8acefd25e7
commit
cfbd869126
12 changed files with 69 additions and 13 deletions
|
@ -80,7 +80,7 @@ int PS4_SYSV_ABI sceAudio3dPortGetAttributesSupported(OrbisAudio3dPortId uiPortI
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(OrbisAudio3dPortId uiPortId, u32* pQueueLevel,
|
int PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(OrbisAudio3dPortId uiPortId, u32* pQueueLevel,
|
||||||
u32* pQueueAvailable) {
|
u32* pQueueAvailable) {
|
||||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
LOG_TRACE(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -971,7 +971,7 @@ s32 PS4_SYSV_ABI sceGnmFindResourcesPublic() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceGnmFlushGarlic() {
|
void PS4_SYSV_ABI sceGnmFlushGarlic() {
|
||||||
LOG_WARNING(Lib_GnmDriver, "(STUBBED) called");
|
LOG_TRACE(Lib_GnmDriver, "(STUBBED) called");
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceGnmGetCoredumpAddress() {
|
int PS4_SYSV_ABI sceGnmGetCoredumpAddress() {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
@ -65,6 +66,15 @@ char* PS4_SYSV_ABI internal_strncpy(char* dest, const char* src, std::size_t cou
|
||||||
return std::strncpy(dest, src, count);
|
return std::strncpy(dest, src, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI internal_strncpy_s(char* dest, size_t destsz, const char* src, size_t count) {
|
||||||
|
#ifdef _WIN64
|
||||||
|
return strncpy_s(dest, destsz, src, count);
|
||||||
|
#else
|
||||||
|
std::strcpy(dest, src);
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
char* PS4_SYSV_ABI internal_strcat(char* dest, const char* src) {
|
char* PS4_SYSV_ABI internal_strcat(char* dest, const char* src) {
|
||||||
return std::strcat(dest, src);
|
return std::strcat(dest, src);
|
||||||
}
|
}
|
||||||
|
@ -237,6 +247,8 @@ void RegisterlibSceLibcInternal(Core::Loader::SymbolsResolver* sym) {
|
||||||
internal_strlen);
|
internal_strlen);
|
||||||
LIB_FUNCTION("6sJWiWSRuqk", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1,
|
LIB_FUNCTION("6sJWiWSRuqk", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1,
|
||||||
internal_strncpy);
|
internal_strncpy);
|
||||||
|
LIB_FUNCTION("YNzNkJzYqEg", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1,
|
||||||
|
internal_strncpy_s);
|
||||||
LIB_FUNCTION("Ls4tzzhimqQ", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1,
|
LIB_FUNCTION("Ls4tzzhimqQ", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1,
|
||||||
internal_strcat);
|
internal_strcat);
|
||||||
LIB_FUNCTION("ob5xAW4ln-0", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1,
|
LIB_FUNCTION("ob5xAW4ln-0", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1,
|
||||||
|
|
|
@ -266,7 +266,7 @@ void Emulator::Run(const std::filesystem::path& file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string game_serial) {
|
void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string game_serial) {
|
||||||
constexpr std::array<SysModules, 10> ModulesToLoad{
|
constexpr std::array<SysModules, 13> ModulesToLoad{
|
||||||
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
||||||
{"libSceFiber.sprx", &Libraries::Fiber::RegisterlibSceFiber},
|
{"libSceFiber.sprx", &Libraries::Fiber::RegisterlibSceFiber},
|
||||||
{"libSceUlt.sprx", nullptr},
|
{"libSceUlt.sprx", nullptr},
|
||||||
|
@ -276,7 +276,10 @@ void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string
|
||||||
{"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
|
{"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
|
||||||
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
||||||
{"libSceJpegEnc.sprx", &Libraries::JpegEnc::RegisterlibSceJpegEnc},
|
{"libSceJpegEnc.sprx", &Libraries::JpegEnc::RegisterlibSceJpegEnc},
|
||||||
{"libSceCesCs.sprx", nullptr}}};
|
{"libSceCesCs.sprx", nullptr},
|
||||||
|
{"libSceFont.sprx", nullptr},
|
||||||
|
{"libSceFontFt.sprx", nullptr},
|
||||||
|
{"libSceFreeTypeOt.sprx", nullptr}}};
|
||||||
|
|
||||||
std::vector<std::filesystem::path> found_modules;
|
std::vector<std::filesystem::path> found_modules;
|
||||||
const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||||
|
|
|
@ -431,6 +431,10 @@ struct Liverpool {
|
||||||
return u64(z_read_base) << 8;
|
return u64(z_read_base) << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 StencilAddress() const {
|
||||||
|
return u64(stencil_read_base) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
u32 NumSamples() const {
|
u32 NumSamples() const {
|
||||||
return 1u << z_info.num_samples; // spec doesn't say it is a log2
|
return 1u << z_info.num_samples; // spec doesn't say it is a log2
|
||||||
}
|
}
|
||||||
|
|
|
@ -616,18 +616,24 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
|
||||||
auto& [image_id, desc] = image_bindings.emplace_back(std::piecewise_construct, std::tuple{},
|
auto& [image_id, desc] = image_bindings.emplace_back(std::piecewise_construct, std::tuple{},
|
||||||
std::tuple{tsharp, image_desc});
|
std::tuple{tsharp, image_desc});
|
||||||
image_id = texture_cache.FindImage(desc);
|
image_id = texture_cache.FindImage(desc);
|
||||||
auto& image = texture_cache.GetImage(image_id);
|
auto* image = &texture_cache.GetImage(image_id);
|
||||||
if (image.binding.is_bound) {
|
if (image->depth_id) {
|
||||||
|
// If this image has an associated depth image, it's a stencil attachment.
|
||||||
|
// Redirect the access to the actual depth-stencil buffer.
|
||||||
|
image_id = image->depth_id;
|
||||||
|
image = &texture_cache.GetImage(image_id);
|
||||||
|
}
|
||||||
|
if (image->binding.is_bound) {
|
||||||
// The image is already bound. In case if it is about to be used as storage we need
|
// The image is already bound. In case if it is about to be used as storage we need
|
||||||
// to force general layout on it.
|
// to force general layout on it.
|
||||||
image.binding.force_general |= image_desc.is_storage;
|
image->binding.force_general |= image_desc.is_storage;
|
||||||
}
|
}
|
||||||
if (image.binding.is_target) {
|
if (image->binding.is_target) {
|
||||||
// The image is already bound as target. Since we read and output to it need to force
|
// The image is already bound as target. Since we read and output to it need to force
|
||||||
// general layout too.
|
// general layout too.
|
||||||
image.binding.force_general = 1u;
|
image->binding.force_general = 1u;
|
||||||
}
|
}
|
||||||
image.binding.is_bound = 1u;
|
image->binding.is_bound = 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second pass to re-bind images that were updated after binding
|
// Second pass to re-bind images that were updated after binding
|
||||||
|
|
|
@ -145,8 +145,10 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
||||||
const ImageInfo& info_)
|
const ImageInfo& info_)
|
||||||
: instance{&instance_}, scheduler{&scheduler_}, info{info_},
|
: instance{&instance_}, scheduler{&scheduler_}, info{info_},
|
||||||
image{instance->GetDevice(), instance->GetAllocator()} {
|
image{instance->GetDevice(), instance->GetAllocator()} {
|
||||||
|
if (info.pixel_format == vk::Format::eUndefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mip_hashes.resize(info.resources.levels);
|
mip_hashes.resize(info.resources.levels);
|
||||||
ASSERT(info.pixel_format != vk::Format::eUndefined);
|
|
||||||
// Here we force `eExtendedUsage` as don't know all image usage cases beforehand. In normal case
|
// Here we force `eExtendedUsage` as don't know all image usage cases beforehand. In normal case
|
||||||
// the texture cache should re-create the resource with the usage requested
|
// the texture cache should re-create the resource with the usage requested
|
||||||
vk::ImageCreateFlags flags{vk::ImageCreateFlagBits::eMutableFormat |
|
vk::ImageCreateFlags flags{vk::ImageCreateFlagBits::eMutableFormat |
|
||||||
|
|
|
@ -92,6 +92,10 @@ struct Image {
|
||||||
return image_view_ids[std::distance(image_view_infos.begin(), it)];
|
return image_view_ids[std::distance(image_view_infos.begin(), it)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssociateDepth(ImageId image_id) {
|
||||||
|
depth_id = image_id;
|
||||||
|
}
|
||||||
|
|
||||||
boost::container::small_vector<vk::ImageMemoryBarrier2, 32> GetBarriers(
|
boost::container::small_vector<vk::ImageMemoryBarrier2, 32> GetBarriers(
|
||||||
vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits2> dst_mask,
|
vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits2> dst_mask,
|
||||||
vk::PipelineStageFlags2 dst_stage, std::optional<SubresourceRange> subres_range);
|
vk::PipelineStageFlags2 dst_stage, std::optional<SubresourceRange> subres_range);
|
||||||
|
@ -116,6 +120,7 @@ struct Image {
|
||||||
VAddr track_addr_end = 0;
|
VAddr track_addr_end = 0;
|
||||||
std::vector<ImageViewInfo> image_view_infos;
|
std::vector<ImageViewInfo> image_view_infos;
|
||||||
std::vector<ImageViewId> image_view_ids;
|
std::vector<ImageViewId> image_view_ids;
|
||||||
|
ImageId depth_id{};
|
||||||
|
|
||||||
// Resource state tracking
|
// Resource state tracking
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -298,6 +298,9 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slice
|
||||||
resources.layers = num_slices;
|
resources.layers = num_slices;
|
||||||
meta_info.htile_addr = buffer.z_info.tile_surface_en ? htile_address : 0;
|
meta_info.htile_addr = buffer.z_info.tile_surface_en ? htile_address : 0;
|
||||||
|
|
||||||
|
stencil_addr = buffer.StencilAddress();
|
||||||
|
stencil_size = pitch * size.height * sizeof(u8);
|
||||||
|
|
||||||
guest_address = buffer.Address();
|
guest_address = buffer.Address();
|
||||||
const auto depth_slice_sz = buffer.GetDepthSliceSize();
|
const auto depth_slice_sz = buffer.GetDepthSliceSize();
|
||||||
guest_size_bytes = depth_slice_sz * num_slices;
|
guest_size_bytes = depth_slice_sz * num_slices;
|
||||||
|
|
|
@ -69,7 +69,7 @@ struct ImageInfo {
|
||||||
} props{}; // Surface properties with impact on various calculation factors
|
} props{}; // Surface properties with impact on various calculation factors
|
||||||
|
|
||||||
vk::Format pixel_format = vk::Format::eUndefined;
|
vk::Format pixel_format = vk::Format::eUndefined;
|
||||||
vk::ImageType type = vk::ImageType::e1D;
|
vk::ImageType type = vk::ImageType::e2D;
|
||||||
SubresourceExtent resources;
|
SubresourceExtent resources;
|
||||||
Extent3D size{1, 1, 1};
|
Extent3D size{1, 1, 1};
|
||||||
u32 num_bits{};
|
u32 num_bits{};
|
||||||
|
|
|
@ -170,7 +170,7 @@ ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info
|
||||||
format = image.info.pixel_format;
|
format = image.info.pixel_format;
|
||||||
aspect = vk::ImageAspectFlagBits::eDepth;
|
aspect = vk::ImageAspectFlagBits::eDepth;
|
||||||
}
|
}
|
||||||
if (image.aspect_mask & vk::ImageAspectFlagBits::eStencil && format == vk::Format::eR8Unorm) {
|
if (image.aspect_mask & vk::ImageAspectFlagBits::eStencil && format == vk::Format::eR8Uint) {
|
||||||
format = image.info.pixel_format;
|
format = image.info.pixel_format;
|
||||||
aspect = vk::ImageAspectFlagBits::eStencil;
|
aspect = vk::ImageAspectFlagBits::eStencil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,6 +443,27 @@ ImageView& TextureCache::FindDepthTarget(BaseDesc& desc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is a stencil attachment, link depth and stencil.
|
||||||
|
if (desc.info.stencil_addr != 0) {
|
||||||
|
ImageId stencil_id{};
|
||||||
|
ForEachImageInRegion(desc.info.stencil_addr, desc.info.stencil_size,
|
||||||
|
[&](ImageId image_id, Image& image) {
|
||||||
|
if (image.info.guest_address == desc.info.stencil_addr) {
|
||||||
|
stencil_id = image_id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!stencil_id) {
|
||||||
|
ImageInfo info{};
|
||||||
|
info.guest_address = desc.info.stencil_addr;
|
||||||
|
info.guest_size_bytes = desc.info.stencil_size;
|
||||||
|
info.size = desc.info.size;
|
||||||
|
stencil_id = slot_images.insert(instance, scheduler, info);
|
||||||
|
RegisterImage(stencil_id);
|
||||||
|
}
|
||||||
|
Image& image = slot_images[stencil_id];
|
||||||
|
image.AssociateDepth(image_id);
|
||||||
|
}
|
||||||
|
|
||||||
return RegisterImageView(image_id, desc.view_info);
|
return RegisterImageView(image_id, desc.view_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue