diff options
Diffstat (limited to 'src/video_core/texture_cache')
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 53 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 4 | ||||
| -rw-r--r-- | src/video_core/texture_cache/util.cpp | 92 |
3 files changed, 125 insertions, 24 deletions
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index b24086fce..fe13cac93 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -49,8 +49,8 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& if constexpr (HAS_DEVICE_MEMORY_INFO) { const s64 device_memory = static_cast<s64>(runtime.GetDeviceLocalMemory()); - const s64 min_spacing_expected = device_memory - 1_GiB - 512_MiB; - const s64 min_spacing_critical = device_memory - 1_GiB; + const s64 min_spacing_expected = device_memory - 1_GiB; + const s64 min_spacing_critical = device_memory - 512_MiB; const s64 mem_threshold = std::min(device_memory, TARGET_THRESHOLD); const s64 min_vacancy_expected = (6 * mem_threshold) / 10; const s64 min_vacancy_critical = (3 * mem_threshold) / 10; @@ -86,10 +86,12 @@ void TextureCache<P>::RunGarbageCollector() { // used by the async decoder thread. return false; } + if (!aggressive_mode && True(image.flags & ImageFlagBits::CostlyLoad)) { + return false; + } const bool must_download = image.IsSafeDownload() && False(image.flags & ImageFlagBits::BadOverlap); - if (!high_priority_mode && - (must_download || True(image.flags & ImageFlagBits::CostlyLoad))) { + if (!high_priority_mode && must_download) { return false; } if (must_download) { @@ -137,7 +139,6 @@ void TextureCache<P>::TickFrame() { TickAsyncDecode(); runtime.TickFrame(); - critical_gc = 0; ++frame_tick; if constexpr (IMPLEMENTS_ASYNC_DOWNLOADS) { @@ -184,6 +185,42 @@ void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) { } template <class P> +void TextureCache<P>::CheckFeedbackLoop(std::span<const ImageViewInOut> views) { + const bool requires_barrier = [&] { + for (const auto& view : views) { + if (!view.id) { + continue; + } + auto& image_view = slot_image_views[view.id]; + + // Check color targets + for (const auto& ct_view_id : render_targets.color_buffer_ids) { + if (ct_view_id) { + auto& ct_view = slot_image_views[ct_view_id]; + if (image_view.image_id == ct_view.image_id) { + return true; + } + } + } + + // Check zeta target + if (render_targets.depth_buffer_id) { + auto& zt_view = slot_image_views[render_targets.depth_buffer_id]; + if (image_view.image_id == zt_view.image_id) { + return true; + } + } + } + + return false; + }(); + + if (requires_barrier) { + runtime.BarrierFeedbackLoop(); + } +} + +template <class P> typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) { if (index > channel_state->graphics_sampler_table.Limit()) { LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index); @@ -1469,7 +1506,7 @@ std::optional<typename TextureCache<P>::BlitImages> TextureCache<P>::GetBlitImag if (!copy.must_accelerate) { do { if (!src_id && !dst_id) { - break; + return std::nullopt; } if (src_id && True(slot_images[src_id].flags & ImageFlagBits::GpuModified)) { break; @@ -1847,10 +1884,6 @@ void TextureCache<P>::RegisterImage(ImageId image_id) { tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); } total_used_memory += Common::AlignUp(tentative_size, 1024); - if (total_used_memory > critical_memory && critical_gc < GC_EMERGENCY_COUNTS) { - RunGarbageCollector(); - critical_gc++; - } image.lru_index = lru_cache.Insert(image_id, frame_tick); ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) { diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 0720494e5..cc27286f7 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -148,6 +148,9 @@ public: /// Fill image_view_ids with the compute images in indices void FillComputeImageViews(std::span<ImageViewInOut> views); + /// Handle feedback loops during draws. + void CheckFeedbackLoop(std::span<const ImageViewInOut> views); + /// Get the sampler from the graphics descriptor table in the specified index Sampler* GetGraphicsSampler(u32 index); @@ -424,7 +427,6 @@ private: u64 minimum_memory; u64 expected_memory; u64 critical_memory; - size_t critical_gc; struct BufferDownload { GPUVAddr address; diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index f1071aa23..95a5b47d8 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp @@ -18,6 +18,8 @@ #include "common/bit_util.h" #include "common/common_types.h" #include "common/div_ceil.h" +#include "common/scratch_buffer.h" +#include "common/settings.h" #include "video_core/compatible_formats.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/memory_manager.h" @@ -28,6 +30,7 @@ #include "video_core/texture_cache/samples_helper.h" #include "video_core/texture_cache/util.h" #include "video_core/textures/astc.h" +#include "video_core/textures/bcn.h" #include "video_core/textures/decoders.h" namespace VideoCommon { @@ -120,7 +123,9 @@ template <u32 GOB_EXTENT> return { .width = AdjustMipBlockSize<GOB_SIZE_X>(num_tiles.width, block_size.width, level), .height = AdjustMipBlockSize<GOB_SIZE_Y>(num_tiles.height, block_size.height, level), - .depth = AdjustMipBlockSize<GOB_SIZE_Z>(num_tiles.depth, block_size.depth, level), + .depth = level == 0 + ? block_size.depth + : AdjustMipBlockSize<GOB_SIZE_Z>(num_tiles.depth, block_size.depth, level), }; } @@ -162,6 +167,13 @@ template <u32 GOB_EXTENT> } [[nodiscard]] constexpr Extent3D TileShift(const LevelInfo& info, u32 level) { + if (level == 0) { + return Extent3D{ + .width = info.block.width, + .height = info.block.height, + .depth = info.block.depth, + }; + } const Extent3D blocks = NumLevelBlocks(info, level); return Extent3D{ .width = AdjustTileSize(info.block.width, GOB_SIZE_X, blocks.width), @@ -585,6 +597,21 @@ u32 CalculateConvertedSizeBytes(const ImageInfo& info) noexcept { return info.size.width * BytesPerBlock(info.format); } static constexpr Extent2D TILE_SIZE{1, 1}; + if (IsPixelFormatASTC(info.format) && Settings::values.astc_recompression.GetValue() != + Settings::AstcRecompression::Uncompressed) { + const u32 bpp_div = + Settings::values.astc_recompression.GetValue() == Settings::AstcRecompression::Bc1 ? 2 + : 1; + // NumBlocksPerLayer doesn't account for this correctly, so we have to do it manually. + u32 output_size = 0; + for (s32 i = 0; i < info.resources.levels; i++) { + const auto mip_size = AdjustMipSize(info.size, i); + const u32 plane_dim = + Common::AlignUp(mip_size.width, 4U) * Common::AlignUp(mip_size.height, 4U); + output_size += (plane_dim * info.size.depth * info.resources.layers) / bpp_div; + } + return output_size; + } return NumBlocksPerLayer(info, TILE_SIZE) * info.resources.layers * CONVERTED_BYTES_PER_BLOCK; } @@ -885,6 +912,7 @@ BufferCopy UploadBufferCopy(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr, void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8> output, std::span<BufferImageCopy> copies) { u32 output_offset = 0; + Common::ScratchBuffer<u8> decode_scratch; const Extent2D tile_size = DefaultBlockSize(info.format); for (BufferImageCopy& copy : copies) { @@ -895,22 +923,58 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8 ASSERT(copy.image_extent == mip_size); ASSERT(copy.buffer_row_length == Common::AlignUp(mip_size.width, tile_size.width)); ASSERT(copy.buffer_image_height == Common::AlignUp(mip_size.height, tile_size.height)); - if (IsPixelFormatASTC(info.format)) { + + const auto input_offset = input.subspan(copy.buffer_offset); + copy.buffer_offset = output_offset; + copy.buffer_row_length = mip_size.width; + copy.buffer_image_height = mip_size.height; + + const auto recompression_setting = Settings::values.astc_recompression.GetValue(); + const bool astc = IsPixelFormatASTC(info.format); + + if (astc && recompression_setting == Settings::AstcRecompression::Uncompressed) { Tegra::Texture::ASTC::Decompress( - input.subspan(copy.buffer_offset), copy.image_extent.width, - copy.image_extent.height, + input_offset, copy.image_extent.width, copy.image_extent.height, copy.image_subresource.num_layers * copy.image_extent.depth, tile_size.width, tile_size.height, output.subspan(output_offset)); + + output_offset += copy.image_extent.width * copy.image_extent.height * + copy.image_subresource.num_layers * CONVERTED_BYTES_PER_BLOCK; + } else if (astc) { + // BC1 uses 0.5 bytes per texel + // BC3 uses 1 byte per texel + const auto compress = recompression_setting == Settings::AstcRecompression::Bc1 + ? Tegra::Texture::BCN::CompressBC1 + : Tegra::Texture::BCN::CompressBC3; + const auto bpp_div = recompression_setting == Settings::AstcRecompression::Bc1 ? 2 : 1; + + const u32 plane_dim = copy.image_extent.width * copy.image_extent.height; + const u32 level_size = plane_dim * copy.image_extent.depth * + copy.image_subresource.num_layers * CONVERTED_BYTES_PER_BLOCK; + decode_scratch.resize_destructive(level_size); + + Tegra::Texture::ASTC::Decompress( + input_offset, copy.image_extent.width, copy.image_extent.height, + copy.image_subresource.num_layers * copy.image_extent.depth, tile_size.width, + tile_size.height, decode_scratch); + + compress(decode_scratch, copy.image_extent.width, copy.image_extent.height, + copy.image_subresource.num_layers * copy.image_extent.depth, + output.subspan(output_offset)); + + const u32 aligned_plane_dim = Common::AlignUp(copy.image_extent.width, 4) * + Common::AlignUp(copy.image_extent.height, 4); + + copy.buffer_size = + (aligned_plane_dim * copy.image_extent.depth * copy.image_subresource.num_layers) / + bpp_div; + output_offset += static_cast<u32>(copy.buffer_size); } else { - DecompressBC4(input.subspan(copy.buffer_offset), copy.image_extent, - output.subspan(output_offset)); - } - copy.buffer_offset = output_offset; - copy.buffer_row_length = mip_size.width; - copy.buffer_image_height = mip_size.height; + DecompressBC4(input_offset, copy.image_extent, output.subspan(output_offset)); - output_offset += copy.image_extent.width * copy.image_extent.height * - copy.image_subresource.num_layers * CONVERTED_BYTES_PER_BLOCK; + output_offset += copy.image_extent.width * copy.image_extent.height * + copy.image_subresource.num_layers * CONVERTED_BYTES_PER_BLOCK; + } } } @@ -1233,7 +1297,9 @@ u32 MapSizeBytes(const ImageBase& image) { static_assert(CalculateLevelSize(LevelInfo{{1920, 1080, 1}, {0, 2, 0}, {1, 1}, 2, 0}, 0) == 0x7f8000); -static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0}, 0) == 0x4000); +static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0}, 0) == 0x40000); + +static_assert(CalculateLevelSize(LevelInfo{{128, 8, 1}, {0, 4, 0}, {1, 1}, 4, 0}, 0) == 0x40000); static_assert(CalculateLevelOffset(PixelFormat::R8_SINT, {1920, 1080, 1}, {0, 2, 0}, 0, 7) == 0x2afc00); |
