diff options
| author | 2022-03-27 05:05:57 +0200 | |
|---|---|---|
| committer | 2023-03-05 12:18:00 +0100 | |
| commit | 8a3411b417f76db786b1d3cfffbd90926abb20ca (patch) | |
| tree | 383070bd0d4a33189f38423ceea9a5692d38ba09 /src/video_core/texture_cache | |
| parent | Merge pull request #9884 from liamwhite/service-cleanup (diff) | |
| download | yuzu-8a3411b417f76db786b1d3cfffbd90926abb20ca.tar.gz yuzu-8a3411b417f76db786b1d3cfffbd90926abb20ca.tar.xz yuzu-8a3411b417f76db786b1d3cfffbd90926abb20ca.zip | |
Engines: Implement Accelerate DMA Texture.
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/image_info.cpp | 45 | ||||
| -rw-r--r-- | src/video_core/texture_cache/image_info.h | 2 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 69 | ||||
| -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 | 98 | ||||
| -rw-r--r-- | src/video_core/texture_cache/util.h | 10 |
7 files changed, 218 insertions, 12 deletions
diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index e9100091e..a1296b574 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp | |||
| @@ -216,10 +216,51 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { | |||
| 216 | .height = config.height, | 216 | .height = config.height, |
| 217 | .depth = 1, | 217 | .depth = 1, |
| 218 | }; | 218 | }; |
| 219 | rescaleable = block.depth == 0; | 219 | rescaleable = block.depth == 0 && size.height > 256; |
| 220 | rescaleable &= size.height > 256; | ||
| 221 | downscaleable = size.height > 512; | 220 | downscaleable = size.height > 512; |
| 222 | } | 221 | } |
| 223 | } | 222 | } |
| 224 | 223 | ||
| 224 | static PixelFormat ByteSizeToFormat(u32 bytes_per_pixel) { | ||
| 225 | switch (bytes_per_pixel) { | ||
| 226 | case 1: | ||
| 227 | return PixelFormat::R8_UINT; | ||
| 228 | case 2: | ||
| 229 | return PixelFormat::R8G8_UINT; | ||
| 230 | case 4: | ||
| 231 | return PixelFormat::A8B8G8R8_UINT; | ||
| 232 | case 8: | ||
| 233 | return PixelFormat::R16G16B16A16_UINT; | ||
| 234 | case 16: | ||
| 235 | return PixelFormat::R32G32B32A32_UINT; | ||
| 236 | default: | ||
| 237 | UNIMPLEMENTED(); | ||
| 238 | return PixelFormat::Invalid; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | ImageInfo::ImageInfo(const Tegra::DMA::ImageOperand& config) noexcept { | ||
| 243 | const u32 bytes_per_pixel = config.bytes_per_pixel; | ||
| 244 | format = ByteSizeToFormat(bytes_per_pixel); | ||
| 245 | type = config.params.block_size.depth > 0 ? ImageType::e3D : ImageType::e2D; | ||
| 246 | num_samples = 1; | ||
| 247 | block = Extent3D{ | ||
| 248 | .width = config.params.block_size.width, | ||
| 249 | .height = config.params.block_size.height, | ||
| 250 | .depth = config.params.block_size.depth, | ||
| 251 | }; | ||
| 252 | size = Extent3D{ | ||
| 253 | .width = config.params.width, | ||
| 254 | .height = config.params.height, | ||
| 255 | .depth = config.params.depth, | ||
| 256 | }; | ||
| 257 | tile_width_spacing = 0; | ||
| 258 | resources.levels = 1; | ||
| 259 | resources.layers = 1; | ||
| 260 | layer_stride = CalculateLayerStride(*this); | ||
| 261 | maybe_unaligned_layer_stride = CalculateLayerSize(*this); | ||
| 262 | rescaleable = block.depth == 0 && size.height > 256; | ||
| 263 | downscaleable = size.height > 512; | ||
| 264 | } | ||
| 265 | |||
| 225 | } // namespace VideoCommon | 266 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 93755e15e..a12f5b44f 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "video_core/engines/fermi_2d.h" | 6 | #include "video_core/engines/fermi_2d.h" |
| 7 | #include "video_core/engines/maxwell_3d.h" | 7 | #include "video_core/engines/maxwell_3d.h" |
| 8 | #include "video_core/engines/maxwell_dma.h" | ||
| 8 | #include "video_core/surface.h" | 9 | #include "video_core/surface.h" |
| 9 | #include "video_core/texture_cache/types.h" | 10 | #include "video_core/texture_cache/types.h" |
| 10 | 11 | ||
| @@ -19,6 +20,7 @@ struct ImageInfo { | |||
| 19 | explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept; | 20 | explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept; |
| 20 | explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept; | 21 | explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept; |
| 21 | explicit ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept; | 22 | explicit ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept; |
| 23 | explicit ImageInfo(const Tegra::DMA::ImageOperand& config) noexcept; | ||
| 22 | 24 | ||
| 23 | PixelFormat format = PixelFormat::Invalid; | 25 | PixelFormat format = PixelFormat::Invalid; |
| 24 | ImageType type = ImageType::e1D; | 26 | ImageType type = ImageType::e1D; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 9dd152fbe..335338434 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -1359,6 +1359,75 @@ std::optional<typename TextureCache<P>::BlitImages> TextureCache<P>::GetBlitImag | |||
| 1359 | } | 1359 | } |
| 1360 | 1360 | ||
| 1361 | template <class P> | 1361 | template <class P> |
| 1362 | ImageId TextureCache<P>::FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr) { | ||
| 1363 | std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | ||
| 1364 | if (!cpu_addr) { | ||
| 1365 | cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info)); | ||
| 1366 | if (!cpu_addr) { | ||
| 1367 | return ImageId{}; | ||
| 1368 | } | ||
| 1369 | } | ||
| 1370 | ImageId image_id{}; | ||
| 1371 | boost::container::small_vector<ImageId, 1> image_ids; | ||
| 1372 | const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) { | ||
| 1373 | if (True(existing_image.flags & ImageFlagBits::Remapped)) { | ||
| 1374 | return false; | ||
| 1375 | } | ||
| 1376 | if (info.type == ImageType::Linear || existing_image.info.type == ImageType::Linear) | ||
| 1377 | [[unlikely]] { | ||
| 1378 | const bool strict_size = True(existing_image.flags & ImageFlagBits::Strong); | ||
| 1379 | const ImageInfo& existing = existing_image.info; | ||
| 1380 | if (existing_image.gpu_addr == gpu_addr && existing.type == info.type && | ||
| 1381 | existing.pitch == info.pitch && | ||
| 1382 | IsPitchLinearSameSize(existing, info, strict_size) && | ||
| 1383 | IsViewCompatible(existing.format, info.format, false, true)) { | ||
| 1384 | image_id = existing_image_id; | ||
| 1385 | image_ids.push_back(existing_image_id); | ||
| 1386 | return true; | ||
| 1387 | } | ||
| 1388 | } else if (IsSubCopy(info, existing_image, gpu_addr)) { | ||
| 1389 | image_id = existing_image_id; | ||
| 1390 | image_ids.push_back(existing_image_id); | ||
| 1391 | return true; | ||
| 1392 | } | ||
| 1393 | return false; | ||
| 1394 | }; | ||
| 1395 | ForEachImageInRegion(*cpu_addr, CalculateGuestSizeInBytes(info), lambda); | ||
| 1396 | if (image_ids.size() <= 1) [[likely]] { | ||
| 1397 | return image_id; | ||
| 1398 | } | ||
| 1399 | auto image_ids_compare = [this](ImageId a, ImageId b) { | ||
| 1400 | auto& image_a = slot_images[a]; | ||
| 1401 | auto& image_b = slot_images[b]; | ||
| 1402 | return image_a.modification_tick < image_b.modification_tick; | ||
| 1403 | }; | ||
| 1404 | return *std::ranges::max_element(image_ids, image_ids_compare); | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | template <class P> | ||
| 1408 | std::optional<std::pair<typename TextureCache<P>::Image*, std::pair<u32, u32>>> | ||
| 1409 | TextureCache<P>::ObtainImage(const Tegra::DMA::ImageOperand& operand, bool mark_as_modified) { | ||
| 1410 | ImageInfo dst_info(operand); | ||
| 1411 | ImageId dst_id = FindDMAImage(dst_info, operand.address); | ||
| 1412 | if (!dst_id) { | ||
| 1413 | return std::nullopt; | ||
| 1414 | } | ||
| 1415 | auto& image = slot_images[dst_id]; | ||
| 1416 | auto base = image.TryFindBase(operand.address); | ||
| 1417 | if (!base) { | ||
| 1418 | return std::nullopt; | ||
| 1419 | } | ||
| 1420 | if (False(image.flags & ImageFlagBits::GpuModified)) { | ||
| 1421 | // No need to waste time on an image that's synced with guest | ||
| 1422 | return std::nullopt; | ||
| 1423 | } | ||
| 1424 | PrepareImage(dst_id, mark_as_modified, false); | ||
| 1425 | auto& new_image = slot_images[dst_id]; | ||
| 1426 | lru_cache.Touch(new_image.lru_index, frame_tick); | ||
| 1427 | return std::make_pair(&new_image, std::make_pair(base->level, base->layer)); | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | template <class P> | ||
| 1362 | SamplerId TextureCache<P>::FindSampler(const TSCEntry& config) { | 1431 | SamplerId TextureCache<P>::FindSampler(const TSCEntry& config) { |
| 1363 | if (std::ranges::all_of(config.raw, [](u64 value) { return value == 0; })) { | 1432 | if (std::ranges::all_of(config.raw, [](u64 value) { return value == 0; })) { |
| 1364 | return NULL_SAMPLER_ID; | 1433 | return NULL_SAMPLER_ID; |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 013836933..848a5d9ea 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -209,6 +209,9 @@ public: | |||
| 209 | /// Pop asynchronous downloads | 209 | /// Pop asynchronous downloads |
| 210 | void PopAsyncFlushes(); | 210 | void PopAsyncFlushes(); |
| 211 | 211 | ||
| 212 | [[nodiscard]] std::optional<std::pair<Image*, std::pair<u32, u32>>> ObtainImage( | ||
| 213 | const Tegra::DMA::ImageOperand& operand, bool mark_as_modified); | ||
| 214 | |||
| 212 | /// Return true when a CPU region is modified from the GPU | 215 | /// Return true when a CPU region is modified from the GPU |
| 213 | [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); | 216 | [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); |
| 214 | 217 | ||
| @@ -300,6 +303,8 @@ private: | |||
| 300 | /// Remove joined images from the cache | 303 | /// Remove joined images from the cache |
| 301 | [[nodiscard]] ImageId JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); | 304 | [[nodiscard]] ImageId JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); |
| 302 | 305 | ||
| 306 | [[nodiscard]] ImageId FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr); | ||
| 307 | |||
| 303 | /// Return a blit image pair from the given guest blit parameters | 308 | /// Return a blit image pair from the given guest blit parameters |
| 304 | [[nodiscard]] std::optional<BlitImages> GetBlitImages( | 309 | [[nodiscard]] std::optional<BlitImages> GetBlitImages( |
| 305 | const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Surface& src, | 310 | const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Surface& src, |
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 0453456b4..a0e10643f 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 { | |||
| 54 | Format = 1 << 1, | 54 | Format = 1 << 1, |
| 55 | Samples = 1 << 2, | 55 | Samples = 1 << 2, |
| 56 | ForceBrokenViews = 1 << 3, | 56 | ForceBrokenViews = 1 << 3, |
| 57 | FormatBpp = 1 << 4, | ||
| 57 | }; | 58 | }; |
| 58 | DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions) | 59 | DECLARE_ENUM_FLAG_OPERATORS(RelaxedOptions) |
| 59 | 60 | ||
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index 697f86641..de37db684 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -743,6 +743,44 @@ std::vector<ImageCopy> MakeShrinkImageCopies(const ImageInfo& dst, const ImageIn | |||
| 743 | return copies; | 743 | return copies; |
| 744 | } | 744 | } |
| 745 | 745 | ||
| 746 | std::vector<ImageCopy> MakeReinterpretImageCopies(const ImageInfo& src, u32 up_scale, | ||
| 747 | u32 down_shift) { | ||
| 748 | std::vector<ImageCopy> copies; | ||
| 749 | copies.reserve(src.resources.levels); | ||
| 750 | const bool is_3d = src.type == ImageType::e3D; | ||
| 751 | for (s32 level = 0; level < src.resources.levels; ++level) { | ||
| 752 | ImageCopy& copy = copies.emplace_back(); | ||
| 753 | copy.src_subresource = SubresourceLayers{ | ||
| 754 | .base_level = level, | ||
| 755 | .base_layer = 0, | ||
| 756 | .num_layers = src.resources.layers, | ||
| 757 | }; | ||
| 758 | copy.dst_subresource = SubresourceLayers{ | ||
| 759 | .base_level = level, | ||
| 760 | .base_layer = 0, | ||
| 761 | .num_layers = src.resources.layers, | ||
| 762 | }; | ||
| 763 | copy.src_offset = Offset3D{ | ||
| 764 | .x = 0, | ||
| 765 | .y = 0, | ||
| 766 | .z = 0, | ||
| 767 | }; | ||
| 768 | copy.dst_offset = Offset3D{ | ||
| 769 | .x = 0, | ||
| 770 | .y = 0, | ||
| 771 | .z = 0, | ||
| 772 | }; | ||
| 773 | const Extent3D mip_size = AdjustMipSize(src.size, level); | ||
| 774 | copy.extent = AdjustSamplesSize(mip_size, src.num_samples); | ||
| 775 | if (is_3d) { | ||
| 776 | copy.extent.depth = src.size.depth; | ||
| 777 | } | ||
| 778 | copy.extent.width = std::max<u32>((copy.extent.width * up_scale) >> down_shift, 1); | ||
| 779 | copy.extent.height = std::max<u32>((copy.extent.height * up_scale) >> down_shift, 1); | ||
| 780 | } | ||
| 781 | return copies; | ||
| 782 | } | ||
| 783 | |||
| 746 | bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config) { | 784 | bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config) { |
| 747 | const GPUVAddr address = config.Address(); | 785 | const GPUVAddr address = config.Address(); |
| 748 | if (address == 0) { | 786 | if (address == 0) { |
| @@ -999,6 +1037,20 @@ bool IsBlockLinearSizeCompatible(const ImageInfo& lhs, const ImageInfo& rhs, u32 | |||
| 999 | } | 1037 | } |
| 1000 | } | 1038 | } |
| 1001 | 1039 | ||
| 1040 | bool IsBlockLinearSizeCompatibleBPPRelaxed(const ImageInfo& lhs, const ImageInfo& rhs, | ||
| 1041 | u32 lhs_level, u32 rhs_level) noexcept { | ||
| 1042 | ASSERT(lhs.type != ImageType::Linear); | ||
| 1043 | ASSERT(rhs.type != ImageType::Linear); | ||
| 1044 | const auto lhs_bpp = BytesPerBlock(lhs.format); | ||
| 1045 | const auto rhs_bpp = BytesPerBlock(rhs.format); | ||
| 1046 | const Extent3D lhs_size = AdjustMipSize(lhs.size, lhs_level); | ||
| 1047 | const Extent3D rhs_size = AdjustMipSize(rhs.size, rhs_level); | ||
| 1048 | return Common::AlignUpLog2(lhs_size.width * lhs_bpp, GOB_SIZE_X_SHIFT) == | ||
| 1049 | Common::AlignUpLog2(rhs_size.width * rhs_bpp, GOB_SIZE_X_SHIFT) && | ||
| 1050 | Common::AlignUpLog2(lhs_size.height, GOB_SIZE_Y_SHIFT) == | ||
| 1051 | Common::AlignUpLog2(rhs_size.height, GOB_SIZE_Y_SHIFT); | ||
| 1052 | } | ||
| 1053 | |||
| 1002 | bool IsPitchLinearSameSize(const ImageInfo& lhs, const ImageInfo& rhs, bool strict_size) noexcept { | 1054 | bool IsPitchLinearSameSize(const ImageInfo& lhs, const ImageInfo& rhs, bool strict_size) noexcept { |
| 1003 | ASSERT(lhs.type == ImageType::Linear); | 1055 | ASSERT(lhs.type == ImageType::Linear); |
| 1004 | ASSERT(rhs.type == ImageType::Linear); | 1056 | ASSERT(rhs.type == ImageType::Linear); |
| @@ -1073,7 +1125,8 @@ std::optional<SubresourceBase> FindSubresource(const ImageInfo& candidate, const | |||
| 1073 | // Format checking is relaxed, but we still have to check for matching bytes per block. | 1125 | // Format checking is relaxed, but we still have to check for matching bytes per block. |
| 1074 | // This avoids creating a view for blits on UE4 titles where formats with different bytes | 1126 | // This avoids creating a view for blits on UE4 titles where formats with different bytes |
| 1075 | // per block are aliased. | 1127 | // per block are aliased. |
| 1076 | if (BytesPerBlock(existing.format) != BytesPerBlock(candidate.format)) { | 1128 | if (BytesPerBlock(existing.format) != BytesPerBlock(candidate.format) && |
| 1129 | False(options & RelaxedOptions::FormatBpp)) { | ||
| 1077 | return std::nullopt; | 1130 | return std::nullopt; |
| 1078 | } | 1131 | } |
| 1079 | } else { | 1132 | } else { |
| @@ -1088,10 +1141,8 @@ std::optional<SubresourceBase> FindSubresource(const ImageInfo& candidate, const | |||
| 1088 | if (existing.type != candidate.type) { | 1141 | if (existing.type != candidate.type) { |
| 1089 | return std::nullopt; | 1142 | return std::nullopt; |
| 1090 | } | 1143 | } |
| 1091 | if (False(options & RelaxedOptions::Samples)) { | 1144 | if (False(options & RelaxedOptions::Samples) && existing.num_samples != candidate.num_samples) { |
| 1092 | if (existing.num_samples != candidate.num_samples) { | 1145 | return std::nullopt; |
| 1093 | return std::nullopt; | ||
| 1094 | } | ||
| 1095 | } | 1146 | } |
| 1096 | if (existing.resources.levels < candidate.resources.levels + base->level) { | 1147 | if (existing.resources.levels < candidate.resources.levels + base->level) { |
| 1097 | return std::nullopt; | 1148 | return std::nullopt; |
| @@ -1101,14 +1152,16 @@ std::optional<SubresourceBase> FindSubresource(const ImageInfo& candidate, const | |||
| 1101 | if (mip_depth < candidate.size.depth + base->layer) { | 1152 | if (mip_depth < candidate.size.depth + base->layer) { |
| 1102 | return std::nullopt; | 1153 | return std::nullopt; |
| 1103 | } | 1154 | } |
| 1104 | } else { | 1155 | } else if (existing.resources.layers < candidate.resources.layers + base->layer) { |
| 1105 | if (existing.resources.layers < candidate.resources.layers + base->layer) { | 1156 | return std::nullopt; |
| 1106 | return std::nullopt; | ||
| 1107 | } | ||
| 1108 | } | 1157 | } |
| 1109 | const bool strict_size = False(options & RelaxedOptions::Size); | 1158 | const bool strict_size = False(options & RelaxedOptions::Size); |
| 1110 | if (!IsBlockLinearSizeCompatible(existing, candidate, base->level, 0, strict_size)) { | 1159 | if (!IsBlockLinearSizeCompatible(existing, candidate, base->level, 0, strict_size)) { |
| 1111 | return std::nullopt; | 1160 | if (False(options & RelaxedOptions::FormatBpp)) { |
| 1161 | return std::nullopt; | ||
| 1162 | } else if (!IsBlockLinearSizeCompatibleBPPRelaxed(existing, candidate, base->level, 0)) { | ||
| 1163 | return std::nullopt; | ||
| 1164 | } | ||
| 1112 | } | 1165 | } |
| 1113 | // TODO: compare block sizes | 1166 | // TODO: compare block sizes |
| 1114 | return base; | 1167 | return base; |
| @@ -1120,6 +1173,31 @@ bool IsSubresource(const ImageInfo& candidate, const ImageBase& image, GPUVAddr | |||
| 1120 | .has_value(); | 1173 | .has_value(); |
| 1121 | } | 1174 | } |
| 1122 | 1175 | ||
| 1176 | bool IsSubCopy(const ImageInfo& candidate, const ImageBase& image, GPUVAddr candidate_addr) { | ||
| 1177 | const std::optional<SubresourceBase> base = image.TryFindBase(candidate_addr); | ||
| 1178 | if (!base) { | ||
| 1179 | return false; | ||
| 1180 | } | ||
| 1181 | const ImageInfo& existing = image.info; | ||
| 1182 | if (existing.resources.levels < candidate.resources.levels + base->level) { | ||
| 1183 | return false; | ||
| 1184 | } | ||
| 1185 | if (existing.type == ImageType::e3D) { | ||
| 1186 | const u32 mip_depth = std::max(1U, existing.size.depth << base->level); | ||
| 1187 | if (mip_depth < candidate.size.depth + base->layer) { | ||
| 1188 | return false; | ||
| 1189 | } | ||
| 1190 | } else { | ||
| 1191 | if (existing.resources.layers < candidate.resources.layers + base->layer) { | ||
| 1192 | return false; | ||
| 1193 | } | ||
| 1194 | } | ||
| 1195 | if (!IsBlockLinearSizeCompatibleBPPRelaxed(existing, candidate, base->level, 0)) { | ||
| 1196 | return false; | ||
| 1197 | } | ||
| 1198 | return true; | ||
| 1199 | } | ||
| 1200 | |||
| 1123 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, | 1201 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, |
| 1124 | const ImageBase* src) { | 1202 | const ImageBase* src) { |
| 1125 | const auto original_dst_format = dst_info.format; | 1203 | const auto original_dst_format = dst_info.format; |
diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h index d103db8ae..84aa6880d 100644 --- a/src/video_core/texture_cache/util.h +++ b/src/video_core/texture_cache/util.h | |||
| @@ -56,6 +56,10 @@ struct OverlapResult { | |||
| 56 | SubresourceBase base, u32 up_scale = 1, | 56 | SubresourceBase base, u32 up_scale = 1, |
| 57 | u32 down_shift = 0); | 57 | u32 down_shift = 0); |
| 58 | 58 | ||
| 59 | [[nodiscard]] std::vector<ImageCopy> MakeReinterpretImageCopies(const ImageInfo& src, | ||
| 60 | u32 up_scale = 1, | ||
| 61 | u32 down_shift = 0); | ||
| 62 | |||
| 59 | [[nodiscard]] bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config); | 63 | [[nodiscard]] bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config); |
| 60 | 64 | ||
| 61 | [[nodiscard]] std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, | 65 | [[nodiscard]] std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, |
| @@ -88,6 +92,9 @@ void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const Ima | |||
| 88 | [[nodiscard]] bool IsPitchLinearSameSize(const ImageInfo& lhs, const ImageInfo& rhs, | 92 | [[nodiscard]] bool IsPitchLinearSameSize(const ImageInfo& lhs, const ImageInfo& rhs, |
| 89 | bool strict_size) noexcept; | 93 | bool strict_size) noexcept; |
| 90 | 94 | ||
| 95 | [[nodiscard]] bool IsBlockLinearSizeCompatibleBPPRelaxed(const ImageInfo& lhs, const ImageInfo& rhs, | ||
| 96 | u32 lhs_level, u32 rhs_level) noexcept; | ||
| 97 | |||
| 91 | [[nodiscard]] std::optional<OverlapResult> ResolveOverlap(const ImageInfo& new_info, | 98 | [[nodiscard]] std::optional<OverlapResult> ResolveOverlap(const ImageInfo& new_info, |
| 92 | GPUVAddr gpu_addr, VAddr cpu_addr, | 99 | GPUVAddr gpu_addr, VAddr cpu_addr, |
| 93 | const ImageBase& overlap, | 100 | const ImageBase& overlap, |
| @@ -106,6 +113,9 @@ void SwizzleImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, const Ima | |||
| 106 | GPUVAddr candidate_addr, RelaxedOptions options, bool broken_views, | 113 | GPUVAddr candidate_addr, RelaxedOptions options, bool broken_views, |
| 107 | bool native_bgr); | 114 | bool native_bgr); |
| 108 | 115 | ||
| 116 | [[nodiscard]] bool IsSubCopy(const ImageInfo& candidate, const ImageBase& image, | ||
| 117 | GPUVAddr candidate_addr); | ||
| 118 | |||
| 109 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, | 119 | void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst, |
| 110 | const ImageBase* src); | 120 | const ImageBase* src); |
| 111 | 121 | ||