diff options
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r-- | src/video_core/texture_cache/format_lookup_table.cpp | 2 | ||||
-rw-r--r-- | src/video_core/texture_cache/formatter.h | 2 | ||||
-rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 105 | ||||
-rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 5 | ||||
-rw-r--r-- | src/video_core/texture_cache/types.h | 1 | ||||
-rw-r--r-- | src/video_core/texture_cache/util.cpp | 9 |
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; + } } } |