mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-26 03:55:37 +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;
|
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) {
|
static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) {
|
||||||
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eTransferSrc |
|
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eTransferSrc |
|
||||||
vk::ImageUsageFlagBits::eTransferDst |
|
vk::ImageUsageFlagBits::eTransferDst |
|
||||||
@ -161,6 +105,9 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
|||||||
if (info.props.is_volume) {
|
if (info.props.is_volume) {
|
||||||
flags |= vk::ImageCreateFlagBits::e2DArrayCompatible;
|
flags |= vk::ImageCreateFlagBits::e2DArrayCompatible;
|
||||||
}
|
}
|
||||||
|
if (info.props.is_block) {
|
||||||
|
flags |= vk::ImageCreateFlagBits::eBlockTexelViewCompatible;
|
||||||
|
}
|
||||||
|
|
||||||
usage_flags = ImageUsageFlags(info);
|
usage_flags = ImageUsageFlags(info);
|
||||||
format_features = FormatFeatureFlags(usage_flags);
|
format_features = FormatFeatureFlags(usage_flags);
|
||||||
@ -372,9 +319,9 @@ void Image::CopyImage(const Image& image) {
|
|||||||
|
|
||||||
boost::container::small_vector<vk::ImageCopy, 14> image_copy{};
|
boost::container::small_vector<vk::ImageCopy, 14> image_copy{};
|
||||||
for (u32 m = 0; m < image.info.resources.levels; ++m) {
|
for (u32 m = 0; m < image.info.resources.levels; ++m) {
|
||||||
const auto mip_w = std::max(info.size.width >> m, 1u);
|
const auto mip_w = std::max(image.info.size.width >> m, 1u);
|
||||||
const auto mip_h = std::max(info.size.height >> m, 1u);
|
const auto mip_h = std::max(image.info.size.height >> m, 1u);
|
||||||
const auto mip_d = std::max(info.size.depth >> m, 1u);
|
const auto mip_d = std::max(image.info.size.depth >> m, 1u);
|
||||||
|
|
||||||
image_copy.emplace_back(vk::ImageCopy{
|
image_copy.emplace_back(vk::ImageCopy{
|
||||||
.srcSubresource{
|
.srcSubresource{
|
||||||
|
@ -152,6 +152,80 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de
|
|||||||
UpdateSize();
|
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() {
|
void ImageInfo::UpdateSize() {
|
||||||
mips_layout.clear();
|
mips_layout.clear();
|
||||||
MipInfo mip_info{};
|
MipInfo mip_info{};
|
||||||
|
@ -25,6 +25,11 @@ struct ImageInfo {
|
|||||||
bool IsTiled() const {
|
bool IsTiled() const {
|
||||||
return tiling_mode != AmdGpu::TilingMode::Display_Linear;
|
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 IsBlockCoded() const;
|
||||||
bool IsPacked() const;
|
bool IsPacked() const;
|
||||||
bool IsDepthStencil() const;
|
bool IsDepthStencil() const;
|
||||||
@ -33,24 +38,8 @@ struct ImageInfo {
|
|||||||
s32 MipOf(const ImageInfo& info) const;
|
s32 MipOf(const ImageInfo& info) const;
|
||||||
s32 SliceOf(const ImageInfo& info, s32 mip) const;
|
s32 SliceOf(const ImageInfo& info, s32 mip) const;
|
||||||
|
|
||||||
/// Verifies if images are compatible for subresource merging.
|
bool IsCompatible(const ImageInfo& info) const;
|
||||||
bool IsCompatible(const ImageInfo& info) const {
|
bool IsTilingCompatible(u32 lhs, u32 rhs) 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateSize();
|
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;
|
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.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.
|
// Very likely this kind of overlap is caused by allocation from a pool.
|
||||||
if (safe_to_delete) {
|
if (safe_to_delete) {
|
||||||
FreeImage(cache_image_id);
|
FreeImage(cache_image_id);
|
||||||
@ -211,6 +212,12 @@ std::tuple<ImageId, int, int> TextureCache::ResolveOverlap(const ImageInfo& imag
|
|||||||
return {depth_image_id, -1, -1};
|
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 ||
|
if (image_info.pixel_format != tex_cache_image.info.pixel_format ||
|
||||||
image_info.guest_size <= tex_cache_image.info.guest_size) {
|
image_info.guest_size <= tex_cache_image.info.guest_size) {
|
||||||
auto result_id = merged_image_id ? merged_image_id : cache_image_id;
|
auto result_id = merged_image_id ? merged_image_id : cache_image_id;
|
||||||
|
Loading…
Reference in New Issue
Block a user