mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-25 11:34:55 +00:00
texture_cache: Handle compressed views of uncompressed images
This commit is contained in:
parent
70c7fd4fab
commit
a7f91d8ff5
@ -14,62 +14,6 @@ namespace VideoCore {
|
||||
|
||||
using namespace Vulkan;
|
||||
|
||||
bool ImageInfo::IsBlockCoded() const {
|
||||
switch (pixel_format) {
|
||||
case vk::Format::eBc1RgbaSrgbBlock:
|
||||
case vk::Format::eBc1RgbaUnormBlock:
|
||||
case vk::Format::eBc1RgbSrgbBlock:
|
||||
case vk::Format::eBc1RgbUnormBlock:
|
||||
case vk::Format::eBc2SrgbBlock:
|
||||
case vk::Format::eBc2UnormBlock:
|
||||
case vk::Format::eBc3SrgbBlock:
|
||||
case vk::Format::eBc3UnormBlock:
|
||||
case vk::Format::eBc4SnormBlock:
|
||||
case vk::Format::eBc4UnormBlock:
|
||||
case vk::Format::eBc5SnormBlock:
|
||||
case vk::Format::eBc5UnormBlock:
|
||||
case vk::Format::eBc6HSfloatBlock:
|
||||
case vk::Format::eBc6HUfloatBlock:
|
||||
case vk::Format::eBc7SrgbBlock:
|
||||
case vk::Format::eBc7UnormBlock:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageInfo::IsPacked() const {
|
||||
switch (pixel_format) {
|
||||
case vk::Format::eB5G5R5A1UnormPack16:
|
||||
[[fallthrough]];
|
||||
case vk::Format::eB5G6R5UnormPack16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageInfo::IsDepthStencil() const {
|
||||
switch (pixel_format) {
|
||||
case vk::Format::eD16Unorm:
|
||||
case vk::Format::eD16UnormS8Uint:
|
||||
case vk::Format::eD32Sfloat:
|
||||
case vk::Format::eD32SfloatS8Uint:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageInfo::HasStencil() const {
|
||||
if (pixel_format == vk::Format::eD32SfloatS8Uint ||
|
||||
pixel_format == vk::Format::eD24UnormS8Uint ||
|
||||
pixel_format == vk::Format::eD16UnormS8Uint) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) {
|
||||
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eTransferSrc |
|
||||
vk::ImageUsageFlagBits::eTransferDst |
|
||||
@ -161,6 +105,9 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
||||
if (info.props.is_volume) {
|
||||
flags |= vk::ImageCreateFlagBits::e2DArrayCompatible;
|
||||
}
|
||||
if (info.props.is_block) {
|
||||
flags |= vk::ImageCreateFlagBits::eBlockTexelViewCompatible;
|
||||
}
|
||||
|
||||
usage_flags = ImageUsageFlags(info);
|
||||
format_features = FormatFeatureFlags(usage_flags);
|
||||
@ -372,9 +319,9 @@ void Image::CopyImage(const Image& image) {
|
||||
|
||||
boost::container::small_vector<vk::ImageCopy, 14> image_copy{};
|
||||
for (u32 m = 0; m < image.info.resources.levels; ++m) {
|
||||
const auto mip_w = std::max(info.size.width >> m, 1u);
|
||||
const auto mip_h = std::max(info.size.height >> m, 1u);
|
||||
const auto mip_d = std::max(info.size.depth >> m, 1u);
|
||||
const auto mip_w = std::max(image.info.size.width >> m, 1u);
|
||||
const auto mip_h = std::max(image.info.size.height >> m, 1u);
|
||||
const auto mip_d = std::max(image.info.size.depth >> m, 1u);
|
||||
|
||||
image_copy.emplace_back(vk::ImageCopy{
|
||||
.srcSubresource{
|
||||
|
@ -152,6 +152,80 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
bool ImageInfo::IsBlockCoded() const {
|
||||
switch (pixel_format) {
|
||||
case vk::Format::eBc1RgbaSrgbBlock:
|
||||
case vk::Format::eBc1RgbaUnormBlock:
|
||||
case vk::Format::eBc1RgbSrgbBlock:
|
||||
case vk::Format::eBc1RgbUnormBlock:
|
||||
case vk::Format::eBc2SrgbBlock:
|
||||
case vk::Format::eBc2UnormBlock:
|
||||
case vk::Format::eBc3SrgbBlock:
|
||||
case vk::Format::eBc3UnormBlock:
|
||||
case vk::Format::eBc4SnormBlock:
|
||||
case vk::Format::eBc4UnormBlock:
|
||||
case vk::Format::eBc5SnormBlock:
|
||||
case vk::Format::eBc5UnormBlock:
|
||||
case vk::Format::eBc6HSfloatBlock:
|
||||
case vk::Format::eBc6HUfloatBlock:
|
||||
case vk::Format::eBc7SrgbBlock:
|
||||
case vk::Format::eBc7UnormBlock:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageInfo::IsPacked() const {
|
||||
switch (pixel_format) {
|
||||
case vk::Format::eB5G5R5A1UnormPack16:
|
||||
[[fallthrough]];
|
||||
case vk::Format::eB5G6R5UnormPack16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageInfo::IsDepthStencil() const {
|
||||
switch (pixel_format) {
|
||||
case vk::Format::eD16Unorm:
|
||||
case vk::Format::eD16UnormS8Uint:
|
||||
case vk::Format::eD32Sfloat:
|
||||
case vk::Format::eD32SfloatS8Uint:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageInfo::HasStencil() const {
|
||||
if (pixel_format == vk::Format::eD32SfloatS8Uint ||
|
||||
pixel_format == vk::Format::eD24UnormS8Uint ||
|
||||
pixel_format == vk::Format::eD16UnormS8Uint) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImageInfo::IsCompatible(const ImageInfo& info) const {
|
||||
return (pixel_format == info.pixel_format && num_samples == info.num_samples &&
|
||||
num_bits == info.num_bits);
|
||||
}
|
||||
|
||||
bool ImageInfo::IsTilingCompatible(u32 lhs, u32 rhs) const {
|
||||
if (lhs == rhs) {
|
||||
return true;
|
||||
}
|
||||
if (lhs == 0x0e && rhs == 0x0d) {
|
||||
return true;
|
||||
}
|
||||
if (lhs == 0x0d && rhs == 0x0e) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageInfo::UpdateSize() {
|
||||
mips_layout.clear();
|
||||
MipInfo mip_info{};
|
||||
|
@ -25,6 +25,11 @@ struct ImageInfo {
|
||||
bool IsTiled() const {
|
||||
return tiling_mode != AmdGpu::TilingMode::Display_Linear;
|
||||
}
|
||||
Extent3D BlockDim() const {
|
||||
const u32 shift = props.is_block ? 2 : 0;
|
||||
return Extent3D{size.width >> shift, size.height >> shift, size.depth};
|
||||
}
|
||||
|
||||
bool IsBlockCoded() const;
|
||||
bool IsPacked() const;
|
||||
bool IsDepthStencil() const;
|
||||
@ -33,24 +38,8 @@ struct ImageInfo {
|
||||
s32 MipOf(const ImageInfo& info) const;
|
||||
s32 SliceOf(const ImageInfo& info, s32 mip) const;
|
||||
|
||||
/// Verifies if images are compatible for subresource merging.
|
||||
bool IsCompatible(const ImageInfo& info) const {
|
||||
return (pixel_format == info.pixel_format && num_samples == info.num_samples &&
|
||||
num_bits == info.num_bits);
|
||||
}
|
||||
|
||||
bool IsTilingCompatible(u32 lhs, u32 rhs) const {
|
||||
if (lhs == rhs) {
|
||||
return true;
|
||||
}
|
||||
if (lhs == 0x0e && rhs == 0x0d) {
|
||||
return true;
|
||||
}
|
||||
if (lhs == 0x0d && rhs == 0x0e) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool IsCompatible(const ImageInfo& info) const;
|
||||
bool IsTilingCompatible(u32 lhs, u32 rhs) const;
|
||||
|
||||
void UpdateSize();
|
||||
|
||||
|
@ -199,7 +199,8 @@ std::tuple<ImageId, int, int> TextureCache::ResolveOverlap(const ImageInfo& imag
|
||||
scheduler.CurrentTick() - tex_cache_image.tick_accessed_last > NumFramesBeforeRemoval;
|
||||
|
||||
if (image_info.guest_address == tex_cache_image.info.guest_address) { // Equal address
|
||||
if (image_info.size != tex_cache_image.info.size) {
|
||||
if (image_info.BlockDim() != tex_cache_image.info.BlockDim() ||
|
||||
image_info.num_bits != tex_cache_image.info.num_bits) {
|
||||
// Very likely this kind of overlap is caused by allocation from a pool.
|
||||
if (safe_to_delete) {
|
||||
FreeImage(cache_image_id);
|
||||
@ -211,6 +212,12 @@ std::tuple<ImageId, int, int> TextureCache::ResolveOverlap(const ImageInfo& imag
|
||||
return {depth_image_id, -1, -1};
|
||||
}
|
||||
|
||||
if (image_info.IsBlockCoded() && !tex_cache_image.info.IsBlockCoded()) {
|
||||
// Compressed view of uncompressed image with same block size.
|
||||
// We need to recreate the image with compressed format and copy.
|
||||
return {ExpandImage(image_info, cache_image_id), -1, -1};
|
||||
}
|
||||
|
||||
if (image_info.pixel_format != tex_cache_image.info.pixel_format ||
|
||||
image_info.guest_size <= tex_cache_image.info.guest_size) {
|
||||
auto result_id = merged_image_id ? merged_image_id : cache_image_id;
|
||||
|
Loading…
Reference in New Issue
Block a user