summaryrefslogtreecommitdiffstats
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/format_lookup_table.cpp2
-rw-r--r--src/video_core/texture_cache/formatter.h2
-rw-r--r--src/video_core/texture_cache/texture_cache.h105
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h5
-rw-r--r--src/video_core/texture_cache/types.h1
-rw-r--r--src/video_core/texture_cache/util.cpp9
6 files changed, 99 insertions, 25 deletions
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp
index ddfb726fe..afa807d5d 100644
--- a/src/video_core/texture_cache/format_lookup_table.cpp
+++ b/src/video_core/texture_cache/format_lookup_table.cpp
@@ -139,6 +139,8 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red,
return PixelFormat::D16_UNORM;
case Hash(TextureFormat::S8D24, UINT, UNORM, UNORM, UNORM, LINEAR):
return PixelFormat::S8_UINT_D24_UNORM;
+ case Hash(TextureFormat::S8D24, UINT, UNORM, UINT, UINT, LINEAR):
+ return PixelFormat::S8_UINT_D24_UNORM;
case Hash(TextureFormat::R8G24, UINT, UNORM, UNORM, UNORM, LINEAR):
return PixelFormat::S8_UINT_D24_UNORM;
case Hash(TextureFormat::D32S8, FLOAT, UINT, UNORM, UNORM, LINEAR):
diff --git a/src/video_core/texture_cache/formatter.h b/src/video_core/texture_cache/formatter.h
index c6cf0583f..b2c81057b 100644
--- a/src/video_core/texture_cache/formatter.h
+++ b/src/video_core/texture_cache/formatter.h
@@ -194,6 +194,8 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str
return "D32_FLOAT";
case PixelFormat::D16_UNORM:
return "D16_UNORM";
+ case PixelFormat::S8_UINT:
+ return "S8_UINT";
case PixelFormat::D24_UNORM_S8_UINT:
return "D24_UNORM_S8_UINT";
case PixelFormat::S8_UINT_D24_UNORM:
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 241f71a91..5aaeb16ca 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -472,9 +472,10 @@ template <class P>
void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
const Tegra::Engines::Fermi2D::Surface& src,
const Tegra::Engines::Fermi2D::Config& copy) {
- const BlitImages images = GetBlitImages(dst, src);
+ const BlitImages images = GetBlitImages(dst, src, copy);
const ImageId dst_id = images.dst_id;
const ImageId src_id = images.src_id;
+
PrepareImage(src_id, false, false);
PrepareImage(dst_id, true, false);
@@ -758,14 +759,18 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
return ImageId{};
}
}
- const bool broken_views = runtime.HasBrokenTextureViewFormats();
+ const bool broken_views =
+ runtime.HasBrokenTextureViewFormats() || True(options & RelaxedOptions::ForceBrokenViews);
const bool native_bgr = runtime.HasNativeBgr();
- ImageId image_id;
+ const bool flexible_formats = True(options & RelaxedOptions::Format);
+ ImageId image_id{};
+ boost::container::small_vector<ImageId, 1> image_ids;
const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) {
if (True(existing_image.flags & ImageFlagBits::Remapped)) {
return false;
}
- if (info.type == ImageType::Linear || existing_image.info.type == ImageType::Linear) {
+ if (info.type == ImageType::Linear || existing_image.info.type == ImageType::Linear)
+ [[unlikely]] {
const bool strict_size = False(options & RelaxedOptions::Size) &&
True(existing_image.flags & ImageFlagBits::Strong);
const ImageInfo& existing = existing_image.info;
@@ -774,17 +779,27 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
IsPitchLinearSameSize(existing, info, strict_size) &&
IsViewCompatible(existing.format, info.format, broken_views, native_bgr)) {
image_id = existing_image_id;
- return true;
+ image_ids.push_back(existing_image_id);
+ return !flexible_formats && existing.format == info.format;
}
} else if (IsSubresource(info, existing_image, gpu_addr, options, broken_views,
native_bgr)) {
image_id = existing_image_id;
- return true;
+ image_ids.push_back(existing_image_id);
+ return !flexible_formats && existing_image.info.format == info.format;
}
return false;
};
ForEachImageInRegion(*cpu_addr, CalculateGuestSizeInBytes(info), lambda);
- return image_id;
+ if (image_ids.size() <= 1) [[likely]] {
+ return image_id;
+ }
+ auto image_ids_compare = [this](ImageId a, ImageId b) {
+ auto& image_a = slot_images[a];
+ auto& image_b = slot_images[b];
+ return image_a.modification_tick < image_b.modification_tick;
+ };
+ return *std::ranges::max_element(image_ids, image_ids_compare);
}
template <class P>
@@ -1076,31 +1091,66 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
template <class P>
typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages(
- const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Surface& src) {
- static constexpr auto FIND_OPTIONS = RelaxedOptions::Format | RelaxedOptions::Samples;
+ const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Surface& src,
+ const Tegra::Engines::Fermi2D::Config& copy) {
+
+ static constexpr auto FIND_OPTIONS = RelaxedOptions::Samples;
const GPUVAddr dst_addr = dst.Address();
const GPUVAddr src_addr = src.Address();
ImageInfo dst_info(dst);
ImageInfo src_info(src);
+ const bool can_be_depth_blit =
+ dst_info.format == src_info.format && copy.filter == Tegra::Engines::Fermi2D::Filter::Point;
ImageId dst_id;
ImageId src_id;
+ RelaxedOptions try_options = FIND_OPTIONS;
+ if (can_be_depth_blit) {
+ try_options |= RelaxedOptions::Format;
+ }
do {
has_deleted_images = false;
- dst_id = FindImage(dst_info, dst_addr, FIND_OPTIONS);
- src_id = FindImage(src_info, src_addr, FIND_OPTIONS);
- const ImageBase* const dst_image = dst_id ? &slot_images[dst_id] : nullptr;
+ src_id = FindImage(src_info, src_addr, try_options);
+ dst_id = FindImage(dst_info, dst_addr, try_options);
const ImageBase* const src_image = src_id ? &slot_images[src_id] : nullptr;
- DeduceBlitImages(dst_info, src_info, dst_image, src_image);
- if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) {
- continue;
+ if (src_image && src_image->info.num_samples > 1) {
+ RelaxedOptions find_options{FIND_OPTIONS | RelaxedOptions::ForceBrokenViews};
+ src_id = FindOrInsertImage(src_info, src_addr, find_options);
+ dst_id = FindOrInsertImage(dst_info, dst_addr, find_options);
+ if (has_deleted_images) {
+ continue;
+ }
+ break;
}
- if (!dst_id) {
- dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{});
+ if (can_be_depth_blit) {
+ const ImageBase* const dst_image = dst_id ? &slot_images[dst_id] : nullptr;
+ DeduceBlitImages(dst_info, src_info, dst_image, src_image);
+ if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) {
+ continue;
+ }
}
if (!src_id) {
src_id = InsertImage(src_info, src_addr, RelaxedOptions{});
}
+ if (!dst_id) {
+ dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{});
+ }
} while (has_deleted_images);
+ const ImageBase& src_image = slot_images[src_id];
+ const ImageBase& dst_image = slot_images[dst_id];
+ const bool native_bgr = runtime.HasNativeBgr();
+ if (GetFormatType(dst_info.format) != GetFormatType(dst_image.info.format) ||
+ GetFormatType(src_info.format) != GetFormatType(src_image.info.format) ||
+ !VideoCore::Surface::IsViewCompatible(dst_info.format, dst_image.info.format, false,
+ native_bgr) ||
+ !VideoCore::Surface::IsViewCompatible(src_info.format, src_image.info.format, false,
+ native_bgr)) {
+ // Make sure the images match the expected format.
+ do {
+ has_deleted_images = false;
+ src_id = FindOrInsertImage(src_info, src_addr, RelaxedOptions{});
+ dst_id = FindOrInsertImage(dst_info, dst_addr, RelaxedOptions{});
+ } while (has_deleted_images);
+ }
return BlitImages{
.dst_id = dst_id,
.src_id = src_id,
@@ -1157,7 +1207,14 @@ template <class P>
ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAddr gpu_addr,
bool is_clear) {
const auto options = is_clear ? RelaxedOptions::Samples : RelaxedOptions{};
- const ImageId image_id = FindOrInsertImage(info, gpu_addr, options);
+ ImageId image_id{};
+ bool delete_state = has_deleted_images;
+ do {
+ has_deleted_images = false;
+ image_id = FindOrInsertImage(info, gpu_addr, options);
+ delete_state |= has_deleted_images;
+ } while (has_deleted_images);
+ has_deleted_images = delete_state;
if (!image_id) {
return NULL_IMAGE_VIEW_ID;
}
@@ -1759,8 +1816,8 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
}
UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D);
UNIMPLEMENTED_IF(src.info.type != ImageType::e2D);
- if constexpr (HAS_PIXEL_FORMAT_CONVERSIONS) {
- return runtime.ConvertImage(dst, src, copies);
+ if (runtime.ShouldReinterpret(dst, src)) {
+ return runtime.ReinterpretImage(dst, src, copies);
}
for (const ImageCopy& copy : copies) {
UNIMPLEMENTED_IF(copy.dst_subresource.num_layers != 1);
@@ -1780,7 +1837,13 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
const SubresourceExtent src_extent{.levels = 1, .layers = 1};
const SubresourceRange dst_range{.base = dst_base, .extent = dst_extent};
const SubresourceRange src_range{.base = src_base, .extent = src_extent};
- const ImageViewInfo dst_view_info(ImageViewType::e2D, dst.info.format, dst_range);
+ PixelFormat dst_format = dst.info.format;
+ if (GetFormatType(src.info.format) == SurfaceType::DepthStencil &&
+ GetFormatType(dst_format) == SurfaceType::ColorTexture &&
+ BytesPerBlock(dst_format) == 4) {
+ dst_format = PixelFormat::A8B8G8R8_UNORM;
+ }
+ const ImageViewInfo dst_view_info(ImageViewType::e2D, dst_format, dst_range);
const ImageViewInfo src_view_info(ImageViewType::e2D, src.info.format, src_range);
const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info);
Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id];
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index a9504c0e8..7107887a6 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -59,8 +59,6 @@ class TextureCache {
static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES;
/// True when the API can provide info about the memory of the device.
static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO;
- /// True when the API provides utilities for pixel format conversions.
- static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = P::HAS_PIXEL_FORMAT_CONVERSIONS;
static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB;
static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB;
@@ -254,7 +252,8 @@ private:
/// Return a blit image pair from the given guest blit parameters
[[nodiscard]] BlitImages GetBlitImages(const Tegra::Engines::Fermi2D::Surface& dst,
- const Tegra::Engines::Fermi2D::Surface& src);
+ const Tegra::Engines::Fermi2D::Surface& src,
+ const Tegra::Engines::Fermi2D::Config& copy);
/// Find or create a sampler from a guest descriptor sampler
[[nodiscard]] SamplerId FindSampler(const TSCEntry& config);
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h
index 5c274abdf..5ac27b3a7 100644
--- a/src/video_core/texture_cache/types.h
+++ b/src/video_core/texture_cache/types.h
@@ -54,6 +54,7 @@ enum class RelaxedOptions : u32 {
Size = 1 << 0,
Format = 1 << 1,
Samples = 1 << 2,
+ ForceBrokenViews = 1 << 3,
};
DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions)
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index ddc9fb13a..7bd31b211 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -1151,6 +1151,7 @@ bool IsSubresource(const ImageInfo& candidate, const ImageBase& image, GPUVAddr
void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst,
const ImageBase* src) {
+ const auto original_dst_format = dst_info.format;
if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) {
src_info.format = src->info.format;
}
@@ -1161,7 +1162,13 @@ void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase*
dst_info.format = src->info.format;
}
if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) {
- src_info.format = dst->info.format;
+ if (src) {
+ if (GetFormatType(src->info.format) == SurfaceType::ColorTexture) {
+ dst_info.format = original_dst_format;
+ }
+ } else {
+ src_info.format = dst->info.format;
+ }
}
}