From 22f4b290b6f0894d29302102f539dd8753961f04 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 18 Jul 2021 18:40:14 +0200 Subject: VideoCore: Initial Setup for the Resolution Scaler. --- src/video_core/texture_cache/image_base.h | 4 + src/video_core/texture_cache/image_info.h | 2 +- src/video_core/texture_cache/texture_cache.h | 113 +++++++++++++++++++++- src/video_core/texture_cache/texture_cache_base.h | 10 ++ 4 files changed, 126 insertions(+), 3 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 0c17a791b..1cd30fd37 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -33,6 +33,10 @@ enum class ImageFlagBits : u32 { ///< garbage collection priority Alias = 1 << 11, ///< This image has aliases and has priority on garbage ///< collection + + // Rescaler + Rescaled = 1 << 12, + RescaleChecked = 1 << 13, }; DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 5049fc36e..16d4cee37 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -15,7 +15,7 @@ using Tegra::Texture::TICEntry; using VideoCore::Surface::PixelFormat; struct ImageInfo { - explicit ImageInfo() = default; + ImageInfo() = default; explicit ImageInfo(const TICEntry& config) noexcept; explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept; explicit ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index f70c1f764..560da4f16 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -35,6 +35,7 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& Tegra::MemoryManager& gpu_memory_) : runtime{runtime_}, rasterizer{rasterizer_}, maxwell3d{maxwell3d_}, kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_} { + runtime.Init(); // Configure null sampler TSCEntry sampler_descriptor{}; sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); @@ -103,6 +104,7 @@ void TextureCache

::TickFrame() { sentenced_images.Tick(); sentenced_framebuffers.Tick(); sentenced_image_view.Tick(); + runtime.TickFrame(); ++frame_tick; } @@ -208,18 +210,63 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { const bool force = flags[Dirty::RenderTargetControl]; flags[Dirty::RenderTargetControl] = false; + bool can_rescale = true; + std::array tmp_color_images{}; + ImageId tmp_depth_image{}; + const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { + if (view_id) { + const auto& view = slot_image_views[view_id]; + const auto image_id = view.image_id; + id_save = image_id; + auto& image = slot_images[image_id]; + can_rescale &= ImageCanRescale(image); + } else { + id_save = CORRUPT_ID; + } + }; for (size_t index = 0; index < NUM_RT; ++index) { ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; if (flags[Dirty::ColorBuffer0 + index] || force) { flags[Dirty::ColorBuffer0 + index] = false; BindRenderTarget(&color_buffer_id, FindColorBuffer(index, is_clear)); } - PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id)); + check_rescale(color_buffer_id, tmp_color_images[index]); } if (flags[Dirty::ZetaBuffer] || force) { flags[Dirty::ZetaBuffer] = false; BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); } + check_rescale(render_targets.depth_buffer_id, tmp_depth_image); + + if (can_rescale) { + const auto scale_up = [this](ImageId image_id) { + if (image_id != CORRUPT_ID) { + Image& image = slot_images[image_id]; + image.ScaleUp(); + } + }; + for (size_t index = 0; index < NUM_RT; ++index) { + scale_up(tmp_color_images[index]); + } + scale_up(tmp_depth_image); + } else { + const auto scale_down = [this](ImageId image_id) { + if (image_id != CORRUPT_ID) { + Image& image = slot_images[image_id]; + image.ScaleDown(); + } + }; + for (size_t index = 0; index < NUM_RT; ++index) { + scale_down(tmp_color_images[index]); + } + scale_down(tmp_depth_image); + } + // Rescale End + + for (size_t index = 0; index < NUM_RT; ++index) { + ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; + PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id)); + } const ImageViewId depth_buffer_id = render_targets.depth_buffer_id; PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id)); @@ -623,6 +670,31 @@ ImageId TextureCache

::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, return image_id; } +template +bool TextureCache

::ImageCanRescale(Image& image) { + if (True(image.flags & ImageFlagBits::Rescaled) || + True(image.flags & ImageFlagBits::RescaleChecked)) { + return true; + } + const auto& info = image.info; + const bool can_this_rescale = + (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; + if (!can_this_rescale) { + image.flags &= ~ImageFlagBits::RescaleChecked; + return false; + } + image.flags |= ImageFlagBits::RescaleChecked; + for (const auto& alias : image.aliased_images) { + Image& other_image = slot_images[alias.id]; + if (!ImageCanRescale(other_image)) { + image.flags &= ~ImageFlagBits::RescaleChecked; + return false; + } + } + image.flags &= ~ImageFlagBits::RescaleChecked; + return true; +} + template ImageId TextureCache

::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, RelaxedOptions options) { @@ -660,12 +732,18 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA std::vector right_aliased_ids; std::unordered_set ignore_textures; std::vector bad_overlap_ids; + std::vector all_siblings; + const bool this_is_linear = info.type == ImageType::Linear; const auto region_check = [&](ImageId overlap_id, ImageBase& overlap) { if (True(overlap.flags & ImageFlagBits::Remapped)) { ignore_textures.insert(overlap_id); return; } - if (info.type == ImageType::Linear) { + const bool overlap_is_linear = overlap.info.type == ImageType::Linear; + if (this_is_linear != overlap_is_linear) { + return; + } + if (this_is_linear && overlap_is_linear) { if (info.pitch == overlap.info.pitch && gpu_addr == overlap.gpu_addr) { // Alias linear images with the same pitch left_aliased_ids.push_back(overlap_id); @@ -681,6 +759,7 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA cpu_addr = solution->cpu_addr; new_info.resources = solution->resources; overlap_ids.push_back(overlap_id); + all_siblings.push_back(overlap_id); return; } static constexpr auto options = RelaxedOptions::Size | RelaxedOptions::Format; @@ -688,10 +767,12 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA if (IsSubresource(new_info, overlap, gpu_addr, options, broken_views, native_bgr)) { left_aliased_ids.push_back(overlap_id); overlap.flags |= ImageFlagBits::Alias; + all_siblings.push_back(overlap_id); } else if (IsSubresource(overlap.info, new_image_base, overlap.gpu_addr, options, broken_views, native_bgr)) { right_aliased_ids.push_back(overlap_id); overlap.flags |= ImageFlagBits::Alias; + all_siblings.push_back(overlap_id); } else { bad_overlap_ids.push_back(overlap_id); overlap.flags |= ImageFlagBits::BadOverlap; @@ -709,8 +790,36 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA } }; ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu); + + bool can_rescale = + (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; + for (const ImageId sibling_id : all_siblings) { + if (!can_rescale) { + break; + } + Image& sibling = slot_images[sibling_id]; + can_rescale &= ImageCanRescale(sibling); + } + + if (can_rescale) { + for (const ImageId sibling_id : all_siblings) { + Image& sibling = slot_images[sibling_id]; + sibling.ScaleUp(); + } + } else { + for (const ImageId sibling_id : all_siblings) { + Image& sibling = slot_images[sibling_id]; + sibling.ScaleDown(); + } + } + const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); Image& new_image = slot_images[new_image_id]; + if (can_rescale) { + new_image.ScaleUp(); + } else { + new_image.ScaleDown(); + } if (!gpu_memory.IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { new_image.flags |= ImageFlagBits::Sparse; diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 2d1893c1c..a4a2c0832 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -142,6 +142,14 @@ public: const Tegra::Engines::Fermi2D::Surface& src, const Tegra::Engines::Fermi2D::Config& copy); + /// Invalidate the contents of the color buffer index + /// These contents become unspecified, the cache can assume aggressive optimizations. + void InvalidateColorBuffer(size_t index); + + /// Invalidate the contents of the depth buffer + /// These contents become unspecified, the cache can assume aggressive optimizations. + void InvalidateDepthBuffer(); + /// Try to find a cached image view in the given CPU address [[nodiscard]] ImageView* TryFindFramebufferImageView(VAddr cpu_addr); @@ -318,6 +326,8 @@ private: /// Returns true if the current clear parameters clear the whole image of a given image view [[nodiscard]] bool IsFullClear(ImageViewId id); + bool ImageCanRescale(Image& image); + Runtime& runtime; VideoCore::RasterizerInterface& rasterizer; Tegra::Engines::Maxwell3D& maxwell3d; -- cgit v1.2.3 From ba18047e8d06584de0ce18cdbb303a6d9a8742aa Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 19 Jul 2021 04:32:03 +0200 Subject: Texture Cache: Implement Vulkan UpScaling & DownScaling --- .../renderer_opengl/gl_texture_cache.cpp | 10 +- .../renderer_vulkan/vk_texture_cache.cpp | 259 +++++++++++++++++++-- src/video_core/renderer_vulkan/vk_texture_cache.h | 10 +- src/video_core/texture_cache/image_info.cpp | 3 + src/video_core/texture_cache/texture_cache.h | 84 +++++-- src/video_core/texture_cache/texture_cache_base.h | 3 + 6 files changed, 327 insertions(+), 42 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 1e594838f..cdd352aef 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -849,20 +849,22 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b } } -void Image::ScaleUp() { +bool Image::ScaleUp() { if (True(flags & ImageFlagBits::Rescaled)) { - return; + return false; } flags |= ImageFlagBits::Rescaled; UNIMPLEMENTED(); + return true; } -void Image::ScaleDown() { +bool Image::ScaleDown() { if (False(flags & ImageFlagBits::Rescaled)) { - return; + return false; } flags &= ~ImageFlagBits::Rescaled; UNIMPLEMENTED(); + return true; } ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index be5b1d84d..668554d1e 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -137,6 +137,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; } const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples); + const bool is_2d = info.type == ImageType::e2D; return VkImageCreateInfo{ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = nullptr, @@ -144,9 +145,9 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { .imageType = ConvertImageType(info.type), .format = format_info.format, .extent{ - .width = ((info.size.width << up) >> down) >> samples_x, - .height = ((info.size.height << up) >> down) >> samples_y, - .depth = (info.size.depth << up) >> down, + .width = ((info.size.width * up) >> down) >> samples_x, + .height = (is_2d ? ((info.size.height * up) >> down) : info.size.height) >> samples_y, + .depth = info.size.depth, }, .mipLevels = static_cast(info.resources.levels), .arrayLayers = static_cast(info.resources.layers), @@ -160,7 +161,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { }; } -[[nodiscard]] vk::Image MakeImage(const Device& device, const ImageInfo& info, u32 up = 0, +[[nodiscard]] vk::Image MakeImage(const Device& device, const ImageInfo& info, u32 up = 1, u32 down = 0) { if (info.type == ImageType::Buffer) { return vk::Image{}; @@ -851,7 +852,6 @@ u64 TextureCacheRuntime::GetDeviceLocalMemory() const { void TextureCacheRuntime::TickFrame() { prescaled_images.Tick(); prescaled_commits.Tick(); - prescaled_views.Tick(); } Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu_addr_, @@ -923,7 +923,7 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span copies) { const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); if (is_rescaled) { - ScaleDown(); + ScaleDown(true); } std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); scheduler->RequestOutsideRenderPassOperationContext(); @@ -978,38 +978,253 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span& blit_regions, + VkImageAspectFlags aspect_mask) { + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([dst_image, src_image, aspect_mask, + regions = std::move(blit_regions)](vk::CommandBuffer cmdbuf) { + const std::array read_barriers{ + VkImageMemoryBarrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_GENERAL, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = src_image, + .subresourceRange{ + .aspectMask = aspect_mask, + .baseMipLevel = 0, + .levelCount = VK_REMAINING_MIP_LEVELS, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }, + VkImageMemoryBarrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_GENERAL, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = dst_image, + .subresourceRange{ + .aspectMask = aspect_mask, + .baseMipLevel = 0, + .levelCount = VK_REMAINING_MIP_LEVELS, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }, + }; + VkImageMemoryBarrier write_barrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = dst_image, + .subresourceRange{ + .aspectMask = aspect_mask, + .baseMipLevel = 0, + .levelCount = VK_REMAINING_MIP_LEVELS, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }; + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, nullptr, nullptr, read_barriers); + const VkFilter vk_filter = VK_FILTER_NEAREST; + cmdbuf.BlitImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions, vk_filter); + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, write_barrier); + }); +} + +bool Image::ScaleUp(bool save_as_backup) { if (True(flags & ImageFlagBits::Rescaled)) { - return; + return false; } ASSERT(info.type != ImageType::Linear); - if (!runtime->is_rescaling_on) { - flags |= ImageFlagBits::Rescaled; - return; - } - flags |= ImageFlagBits::Rescaled; scaling_count++; ASSERT(scaling_count < 10); - return; + flags |= ImageFlagBits::Rescaled; + /*if (!runtime->is_rescaling_on) { + return; + }*/ + const auto& resolution = runtime->resolution; + vk::Image rescaled_image = + MakeImage(runtime->device, info, resolution.up_scale, resolution.down_shift); + MemoryCommit new_commit( + runtime->memory_allocator.Commit(rescaled_image, MemoryUsage::DeviceLocal)); + + const auto scale_up = [&](u32 value) { + return (value * resolution.up_scale) >> resolution.down_shift; + }; + + const bool is_2d = info.type == ImageType::e2D; + boost::container::small_vector vkRegions(info.resources.levels); + for (s32 level = 0; level < info.resources.levels; level++) { + VkImageBlit blit{ + .srcSubresource{ + .aspectMask = aspect_mask, + .mipLevel = u32(level), + .baseArrayLayer = 0, + .layerCount = u32(info.resources.layers), + }, + .srcOffsets{ + { + .x = 0, + .y = 0, + .z = 0, + }, + { + .x = s32(info.size.width), + .y = s32(info.size.height), + .z = 1, + }, + }, + .dstSubresource{ + .aspectMask = aspect_mask, + .mipLevel = u32(level), + .baseArrayLayer = 0, + .layerCount = u32(info.resources.layers), + }, + .dstOffsets{ + { + .x = 0, + .y = 0, + .z = 0, + }, + { + .x = s32(scale_up(info.size.width)), + .y = is_2d ? s32(scale_up(info.size.height)) : s32(info.size.height), + .z = 1, + }, + }, + }; + vkRegions.push_back(blit); + } + BlitScale(*scheduler, *image, *rescaled_image, vkRegions, aspect_mask); + if (save_as_backup) { + backup_image = std::move(image); + backup_commit = std::move(commit); + has_backup = true; + } else { + runtime->prescaled_images.Push(std::move(image)); + runtime->prescaled_commits.Push(std::move(commit)); + } + image = std::move(rescaled_image); + commit = std::move(new_commit); + return true; } -void Image::ScaleDown() { +void Image::SwapBackup() { + ASSERT(has_backup); + runtime->prescaled_images.Push(std::move(image)); + runtime->prescaled_commits.Push(std::move(commit)); + image = std::move(backup_image); + commit = std::move(backup_commit); + has_backup = false; +} + +bool Image::ScaleDown(bool save_as_backup) { if (False(flags & ImageFlagBits::Rescaled)) { - return; + return false; } ASSERT(info.type != ImageType::Linear); - if (!runtime->is_rescaling_on) { - flags &= ~ImageFlagBits::Rescaled; - return; - } flags &= ~ImageFlagBits::Rescaled; scaling_count++; ASSERT(scaling_count < 10); - return; + /*if (!runtime->is_rescaling_on) { + return false; + }*/ + + const auto& resolution = runtime->resolution; + vk::Image downscaled_image = + MakeImage(runtime->device, info, resolution.up_scale, resolution.down_shift); + MemoryCommit new_commit( + runtime->memory_allocator.Commit(downscaled_image, MemoryUsage::DeviceLocal)); + + const auto scale_up = [&](u32 value) { + return (value * resolution.up_scale) >> resolution.down_shift; + }; + + const bool is_2d = info.type == ImageType::e2D; + boost::container::small_vector vkRegions(info.resources.levels); + for (s32 level = 0; level < info.resources.levels; level++) { + VkImageBlit blit{ + .srcSubresource{ + .aspectMask = aspect_mask, + .mipLevel = u32(level), + .baseArrayLayer = 0, + .layerCount = u32(info.resources.layers), + }, + .srcOffsets{ + { + .x = 0, + .y = 0, + .z = 0, + }, + { + .x = s32(scale_up(info.size.width)), + .y = is_2d ? s32(scale_up(info.size.height)) : s32(info.size.height), + .z = 1, + }, + }, + .dstSubresource{ + .aspectMask = aspect_mask, + .mipLevel = u32(level), + .baseArrayLayer = 0, + .layerCount = u32(info.resources.layers), + }, + .dstOffsets{ + { + .x = 0, + .y = 0, + .z = 0, + }, + { + .x = s32(info.size.width), + .y = s32(info.size.height), + .z = 1, + }, + }, + }; + vkRegions.push_back(blit); + } + BlitScale(*scheduler, *image, *downscaled_image, vkRegions, aspect_mask); + if (save_as_backup) { + backup_image = std::move(image); + backup_commit = std::move(commit); + has_backup = true; + } else { + runtime->prescaled_images.Push(std::move(image)); + runtime->prescaled_commits.Push(std::move(commit)); + } + image = std::move(downscaled_image); + commit = std::move(new_commit); + return true; } ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index f7e782c44..958a64651 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -45,7 +45,6 @@ struct TextureCacheRuntime { static constexpr size_t TICKS_TO_DESTROY = 6; DelayedDestructionRing prescaled_images; DelayedDestructionRing prescaled_commits; - DelayedDestructionRing prescaled_views; Settings::ResolutionScalingInfo resolution; bool is_rescaling_on{}; @@ -126,9 +125,11 @@ public: return std::exchange(initialized, true); } - void ScaleUp(); + bool ScaleUp(bool save_as_backup = false); - void ScaleDown(); + bool ScaleDown(bool save_as_backup = false); + + void SwapBackup(); private: VKScheduler* scheduler; @@ -140,6 +141,9 @@ private: bool initialized = false; TextureCacheRuntime* runtime; u32 scaling_count{}; + vk::Image backup_image{}; + MemoryCommit backup_commit{}; + bool has_backup{}; }; class ImageView : public VideoCommon::ImageViewBase { diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 64fd7010a..022ca9033 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -41,6 +41,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { ASSERT(config.BaseLayer() == 0); type = ImageType::e1D; size.width = config.Width(); + resources.layers = 1; break; case TextureType::Texture1DArray: UNIMPLEMENTED_IF(config.BaseLayer() != 0); @@ -82,10 +83,12 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { size.width = config.Width(); size.height = config.Height(); size.depth = config.Depth(); + resources.layers = 1; break; case TextureType::Texture1DBuffer: type = ImageType::Buffer; size.width = config.Width(); + resources.layers = 1; break; default: UNREACHABLE_MSG("Invalid texture_type={}", static_cast(config.texture_type.Value())); diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 560da4f16..95a9e8fe9 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -242,24 +242,36 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { const auto scale_up = [this](ImageId image_id) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; - image.ScaleUp(); + return ScaleUp(image); } + return false; }; for (size_t index = 0; index < NUM_RT; ++index) { - scale_up(tmp_color_images[index]); + if (scale_up(tmp_color_images[index])) { + BindRenderTarget(&render_targets.color_buffer_ids[index], + FindColorBuffer(index, is_clear)); + } + } + if (scale_up(tmp_depth_image)) { + BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); } - scale_up(tmp_depth_image); } else { const auto scale_down = [this](ImageId image_id) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; - image.ScaleDown(); + return ScaleDown(image); } + return false; }; for (size_t index = 0; index < NUM_RT; ++index) { - scale_down(tmp_color_images[index]); + if (scale_down(tmp_color_images[index])) { + BindRenderTarget(&render_targets.color_buffer_ids[index], + FindColorBuffer(index, is_clear)); + } + } + if (scale_down(tmp_depth_image)) { + BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); } - scale_down(tmp_depth_image); } // Rescale End @@ -695,6 +707,47 @@ bool TextureCache

::ImageCanRescale(Image& image) { return true; } +template +void TextureCache

::InvalidateScale(Image& image, bool invalidate_rt) { + const std::span image_view_ids = image.image_view_ids; + if (invalidate_rt) { + auto& dirty = maxwell3d.dirty.flags; + dirty[Dirty::RenderTargets] = true; + dirty[Dirty::ZetaBuffer] = true; + for (size_t rt = 0; rt < NUM_RT; ++rt) { + dirty[Dirty::ColorBuffer0 + rt] = true; + } + for (const ImageViewId image_view_id : image_view_ids) { + std::ranges::replace(render_targets.color_buffer_ids, image_view_id, ImageViewId{}); + if (render_targets.depth_buffer_id == image_view_id) { + render_targets.depth_buffer_id = ImageViewId{}; + } + } + } + RemoveImageViewReferences(image_view_ids); + RemoveFramebuffers(image_view_ids); +} + +template +bool TextureCache

::ScaleUp(Image& image, bool invalidate_rt) { + const bool rescaled = image.ScaleUp(); + if (!rescaled) { + return false; + } + InvalidateScale(image, invalidate_rt); + return true; +} + +template +bool TextureCache

::ScaleDown(Image& image, bool invalidate_rt) { + const bool rescaled = image.ScaleDown(); + if (!rescaled) { + return false; + } + InvalidateScale(image, invalidate_rt); + return true; +} + template ImageId TextureCache

::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, RelaxedOptions options) { @@ -793,33 +846,32 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA bool can_rescale = (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; + bool any_rescaled = false; for (const ImageId sibling_id : all_siblings) { if (!can_rescale) { break; } Image& sibling = slot_images[sibling_id]; can_rescale &= ImageCanRescale(sibling); + any_rescaled |= True(sibling.flags & ImageFlagBits::Rescaled); } + can_rescale &= any_rescaled; + if (can_rescale) { for (const ImageId sibling_id : all_siblings) { Image& sibling = slot_images[sibling_id]; - sibling.ScaleUp(); + ScaleUp(sibling, true); } } else { for (const ImageId sibling_id : all_siblings) { Image& sibling = slot_images[sibling_id]; - sibling.ScaleDown(); + ScaleDown(sibling, true); } } const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); Image& new_image = slot_images[new_image_id]; - if (can_rescale) { - new_image.ScaleUp(); - } else { - new_image.ScaleDown(); - } if (!gpu_memory.IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { new_image.flags |= ImageFlagBits::Sparse; @@ -840,6 +892,12 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA // TODO: Only upload what we need RefreshContents(new_image, new_image_id); + if (can_rescale) { + new_image.ScaleUp(); + } else { + new_image.ScaleDown(); + } + for (const ImageId overlap_id : overlap_ids) { Image& overlap = slot_images[overlap_id]; if (overlap.info.num_samples != new_image.info.num_samples) { diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index a4a2c0832..042678786 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -327,6 +327,9 @@ private: [[nodiscard]] bool IsFullClear(ImageViewId id); bool ImageCanRescale(Image& image); + void InvalidateScale(Image& image, bool invalidate_rt = false); + bool ScaleUp(Image& image, bool invalidate_rt = false); + bool ScaleDown(Image& image, bool invalidate_rt = false); Runtime& runtime; VideoCore::RasterizerInterface& rasterizer; -- cgit v1.2.3 From 84f2aea8962146be899131b032fcdf9b4e1f6ddf Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 20 Jul 2021 07:40:05 +0200 Subject: Texture Cache: More rescaling fixes. --- .../renderer_opengl/gl_texture_cache.cpp | 4 +- .../renderer_vulkan/vk_texture_cache.cpp | 8 + src/video_core/texture_cache/texture_cache.h | 162 +++++++++++---------- src/video_core/texture_cache/texture_cache_base.h | 6 +- 4 files changed, 96 insertions(+), 84 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 9b2a09007..2d9f770cd 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -918,7 +918,7 @@ bool Image::ScaleUp() { return false; } flags |= ImageFlagBits::Rescaled; - Scale(); + //Scale(); return true; } @@ -927,7 +927,7 @@ bool Image::ScaleDown() { return false; } flags &= ~ImageFlagBits::Rescaled; - Scale(); + //Scale(); return true; } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 668554d1e..5fd190825 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1078,6 +1078,10 @@ bool Image::ScaleUp(bool save_as_backup) { MemoryCommit new_commit( runtime->memory_allocator.Commit(rescaled_image, MemoryUsage::DeviceLocal)); + if (aspect_mask == 0) { + aspect_mask = ImageAspectMask(info.format); + } + const auto scale_up = [&](u32 value) { return (value * resolution.up_scale) >> resolution.down_shift; }; @@ -1170,6 +1174,10 @@ bool Image::ScaleDown(bool save_as_backup) { return (value * resolution.up_scale) >> resolution.down_shift; }; + if (aspect_mask == 0) { + aspect_mask = ImageAspectMask(info.format); + } + const bool is_2d = info.type == ImageType::e2D; boost::container::small_vector vkRegions(info.resources.levels); for (s32 level = 0; level < info.resources.levels; level++) { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 95a9e8fe9..b7d1ae92d 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -204,75 +204,68 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id)); return; } - flags[Dirty::RenderTargets] = false; - - // Render target control is used on all render targets, so force look ups when this one is up - const bool force = flags[Dirty::RenderTargetControl]; - flags[Dirty::RenderTargetControl] = false; - - bool can_rescale = true; - std::array tmp_color_images{}; - ImageId tmp_depth_image{}; - const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { - if (view_id) { - const auto& view = slot_image_views[view_id]; - const auto image_id = view.image_id; - id_save = image_id; - auto& image = slot_images[image_id]; - can_rescale &= ImageCanRescale(image); - } else { - id_save = CORRUPT_ID; - } - }; - for (size_t index = 0; index < NUM_RT; ++index) { - ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; - if (flags[Dirty::ColorBuffer0 + index] || force) { - flags[Dirty::ColorBuffer0 + index] = false; - BindRenderTarget(&color_buffer_id, FindColorBuffer(index, is_clear)); - } - check_rescale(color_buffer_id, tmp_color_images[index]); - } - if (flags[Dirty::ZetaBuffer] || force) { - flags[Dirty::ZetaBuffer] = false; - BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); - } - check_rescale(render_targets.depth_buffer_id, tmp_depth_image); - if (can_rescale) { - const auto scale_up = [this](ImageId image_id) { - if (image_id != CORRUPT_ID) { - Image& image = slot_images[image_id]; - return ScaleUp(image); + do { + flags[Dirty::RenderTargets] = false; + + has_deleted_images = false; + // Render target control is used on all render targets, so force look ups when this one is + // up + const bool force = flags[Dirty::RenderTargetControl]; + flags[Dirty::RenderTargetControl] = false; + + bool can_rescale = true; + std::array tmp_color_images{}; + ImageId tmp_depth_image{}; + const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { + if (view_id) { + const auto& view = slot_image_views[view_id]; + const auto image_id = view.image_id; + id_save = image_id; + auto& image = slot_images[image_id]; + can_rescale &= ImageCanRescale(image); + } else { + id_save = CORRUPT_ID; } - return false; }; for (size_t index = 0; index < NUM_RT; ++index) { - if (scale_up(tmp_color_images[index])) { - BindRenderTarget(&render_targets.color_buffer_ids[index], - FindColorBuffer(index, is_clear)); + ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; + if (flags[Dirty::ColorBuffer0 + index] || force) { + flags[Dirty::ColorBuffer0 + index] = false; + BindRenderTarget(&color_buffer_id, FindColorBuffer(index, is_clear)); } + check_rescale(color_buffer_id, tmp_color_images[index]); } - if (scale_up(tmp_depth_image)) { + if (flags[Dirty::ZetaBuffer] || force) { + flags[Dirty::ZetaBuffer] = false; BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); } - } else { - const auto scale_down = [this](ImageId image_id) { - if (image_id != CORRUPT_ID) { - Image& image = slot_images[image_id]; - return ScaleDown(image); + check_rescale(render_targets.depth_buffer_id, tmp_depth_image); + + if (can_rescale) { + const auto scale_up = [this](ImageId image_id) { + if (image_id != CORRUPT_ID) { + Image& image = slot_images[image_id]; + ScaleUp(image); + } + }; + for (size_t index = 0; index < NUM_RT; ++index) { + scale_up(tmp_color_images[index]); } - return false; - }; - for (size_t index = 0; index < NUM_RT; ++index) { - if (scale_down(tmp_color_images[index])) { - BindRenderTarget(&render_targets.color_buffer_ids[index], - FindColorBuffer(index, is_clear)); + scale_up(tmp_depth_image); + } else { + const auto scale_down = [this](ImageId image_id) { + if (image_id != CORRUPT_ID) { + Image& image = slot_images[image_id]; + ScaleDown(image); + } + }; + for (size_t index = 0; index < NUM_RT; ++index) { + scale_down(tmp_color_images[index]); } + scale_down(tmp_depth_image); } - if (scale_down(tmp_depth_image)) { - BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear)); - } - } + } while (has_deleted_images); // Rescale End for (size_t index = 0; index < NUM_RT; ++index) { @@ -708,43 +701,54 @@ bool TextureCache

::ImageCanRescale(Image& image) { } template -void TextureCache

::InvalidateScale(Image& image, bool invalidate_rt) { +void TextureCache

::InvalidateScale(Image& image) { const std::span image_view_ids = image.image_view_ids; - if (invalidate_rt) { - auto& dirty = maxwell3d.dirty.flags; - dirty[Dirty::RenderTargets] = true; - dirty[Dirty::ZetaBuffer] = true; - for (size_t rt = 0; rt < NUM_RT; ++rt) { - dirty[Dirty::ColorBuffer0 + rt] = true; - } - for (const ImageViewId image_view_id : image_view_ids) { - std::ranges::replace(render_targets.color_buffer_ids, image_view_id, ImageViewId{}); - if (render_targets.depth_buffer_id == image_view_id) { - render_targets.depth_buffer_id = ImageViewId{}; - } + auto& dirty = maxwell3d.dirty.flags; + dirty[Dirty::RenderTargets] = true; + dirty[Dirty::ZetaBuffer] = true; + for (size_t rt = 0; rt < NUM_RT; ++rt) { + dirty[Dirty::ColorBuffer0 + rt] = true; + } + for (const ImageViewId image_view_id : image_view_ids) { + std::ranges::replace(render_targets.color_buffer_ids, image_view_id, ImageViewId{}); + if (render_targets.depth_buffer_id == image_view_id) { + render_targets.depth_buffer_id = ImageViewId{}; } } RemoveImageViewReferences(image_view_ids); RemoveFramebuffers(image_view_ids); + for (const ImageViewId image_view_id : image_view_ids) { + sentenced_image_view.Push(std::move(slot_image_views[image_view_id])); + slot_image_views.erase(image_view_id); + } + image.image_view_ids.clear(); + image.image_view_infos.clear(); + if constexpr (ENABLE_VALIDATION) { + std::ranges::fill(graphics_image_view_ids, CORRUPT_ID); + std::ranges::fill(compute_image_view_ids, CORRUPT_ID); + } + graphics_image_table.Invalidate(); + compute_image_table.Invalidate(); + has_deleted_images = true; } template -bool TextureCache

::ScaleUp(Image& image, bool invalidate_rt) { +bool TextureCache

::ScaleUp(Image& image) { const bool rescaled = image.ScaleUp(); if (!rescaled) { return false; } - InvalidateScale(image, invalidate_rt); + InvalidateScale(image); return true; } template -bool TextureCache

::ScaleDown(Image& image, bool invalidate_rt) { +bool TextureCache

::ScaleDown(Image& image) { const bool rescaled = image.ScaleDown(); if (!rescaled) { return false; } - InvalidateScale(image, invalidate_rt); + InvalidateScale(image); return true; } @@ -861,12 +865,12 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA if (can_rescale) { for (const ImageId sibling_id : all_siblings) { Image& sibling = slot_images[sibling_id]; - ScaleUp(sibling, true); + ScaleUp(sibling); } } else { for (const ImageId sibling_id : all_siblings) { Image& sibling = slot_images[sibling_id]; - ScaleDown(sibling, true); + ScaleDown(sibling); } } @@ -893,9 +897,9 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA RefreshContents(new_image, new_image_id); if (can_rescale) { - new_image.ScaleUp(); + ScaleUp(new_image); } else { - new_image.ScaleDown(); + ScaleDown(new_image); } for (const ImageId overlap_id : overlap_ids) { diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 042678786..cdd99242b 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -327,9 +327,9 @@ private: [[nodiscard]] bool IsFullClear(ImageViewId id); bool ImageCanRescale(Image& image); - void InvalidateScale(Image& image, bool invalidate_rt = false); - bool ScaleUp(Image& image, bool invalidate_rt = false); - bool ScaleDown(Image& image, bool invalidate_rt = false); + void InvalidateScale(Image& image); + bool ScaleUp(Image& image); + bool ScaleDown(Image& image); Runtime& runtime; VideoCore::RasterizerInterface& rasterizer; -- cgit v1.2.3 From 778700ff9d6eca96945deebcd4415e70d58330d9 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 20 Jul 2021 19:36:38 +0200 Subject: TextureCache: Modify Viewports/Scissors according to Rescale. --- src/video_core/dirty_flags.h | 3 +- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 87 +++++++++++++++-------- src/video_core/renderer_vulkan/vk_state_tracker.h | 6 +- src/video_core/texture_cache/texture_cache.h | 25 ++++++- src/video_core/texture_cache/texture_cache_base.h | 3 + src/yuzu/configuration/config.cpp | 4 ++ 6 files changed, 93 insertions(+), 35 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/dirty_flags.h b/src/video_core/dirty_flags.h index f11ff5d94..d63ad5a35 100644 --- a/src/video_core/dirty_flags.h +++ b/src/video_core/dirty_flags.h @@ -29,7 +29,8 @@ enum : u8 { ColorBuffer6, ColorBuffer7, ZetaBuffer, - Rescale, + RescaleViewports, + RescaleScissors, VertexBuffers, VertexBuffer0, diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 30b47a7a0..7a7374b78 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -58,19 +58,14 @@ struct DrawParams { bool is_indexed; }; -VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index) { +VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) { const auto& src = regs.viewport_transform[index]; - const float width = src.scale_x * 2.0f; - float y = src.translate_y - src.scale_y; - float height = src.scale_y * 2.0f; - if (regs.screen_y_control.y_negate) { - y += height; - height = -height; - } + const float width = src.scale_x * 2.0f * scale; + const float height = src.scale_y * 2.0f * scale; const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f; VkViewport viewport{ - .x = src.translate_x - src.scale_x, - .y = y, + .x = (src.translate_x - src.scale_x) * scale, + .y = (src.translate_y - src.scale_y) * scale, .width = width != 0.0f ? width : 1.0f, .height = height != 0.0f ? height : 1.0f, .minDepth = src.translate_z - src.scale_z * reduce_z, @@ -83,14 +78,21 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in return viewport; } -VkRect2D GetScissorState(const Maxwell& regs, size_t index) { +VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u32 down_shift = 0) { const auto& src = regs.scissor_test[index]; VkRect2D scissor; + const auto scale_up = [&](u32 value) -> u32 { + if (value == 0) { + return 0U; + } + const u32 converted_value = (value * up_scale) >> down_shift; + return std::max(converted_value, 1U); + }; if (src.enable) { - scissor.offset.x = static_cast(src.min_x); - scissor.offset.y = static_cast(src.min_y); - scissor.extent.width = src.max_x - src.min_x; - scissor.extent.height = src.max_y - src.min_y; + scissor.offset.x = static_cast(scale_up(src.min_x)); + scissor.offset.y = static_cast(scale_up(src.min_y)); + scissor.extent.width = scale_up(src.max_x - src.min_x); + scissor.extent.height = scale_up(src.max_y - src.min_y); } else { scissor.offset.x = 0; scissor.offset.y = 0; @@ -214,8 +216,15 @@ void RasterizerVulkan::Clear() { const VkExtent2D render_area = framebuffer->RenderArea(); scheduler.RequestRenderpass(framebuffer); + u32 up_scale = 1; + u32 down_shift = 0; + if (texture_cache.IsRescaling()) { + up_scale = Settings::values.resolution_info.up_scale; + down_shift = Settings::values.resolution_info.down_shift; + } + VkClearRect clear_rect{ - .rect = GetScissorState(regs, 0), + .rect = GetScissorState(regs, 0, up_scale, down_shift), .baseArrayLayer = regs.clear_buffers.layer, .layerCount = 1, }; @@ -595,15 +604,17 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg if (!state_tracker.TouchViewports()) { return; } + const float scale = + texture_cache.IsRescaling() ? Settings::values.resolution_info.up_factor : 1.0f; const std::array viewports{ - GetViewportState(device, regs, 0), GetViewportState(device, regs, 1), - GetViewportState(device, regs, 2), GetViewportState(device, regs, 3), - GetViewportState(device, regs, 4), GetViewportState(device, regs, 5), - GetViewportState(device, regs, 6), GetViewportState(device, regs, 7), - GetViewportState(device, regs, 8), GetViewportState(device, regs, 9), - GetViewportState(device, regs, 10), GetViewportState(device, regs, 11), - GetViewportState(device, regs, 12), GetViewportState(device, regs, 13), - GetViewportState(device, regs, 14), GetViewportState(device, regs, 15), + GetViewportState(device, regs, 0, scale), GetViewportState(device, regs, 1, scale), + GetViewportState(device, regs, 2, scale), GetViewportState(device, regs, 3, scale), + GetViewportState(device, regs, 4, scale), GetViewportState(device, regs, 5, scale), + GetViewportState(device, regs, 6, scale), GetViewportState(device, regs, 7, scale), + GetViewportState(device, regs, 8, scale), GetViewportState(device, regs, 9, scale), + GetViewportState(device, regs, 10, scale), GetViewportState(device, regs, 11, scale), + GetViewportState(device, regs, 12, scale), GetViewportState(device, regs, 13, scale), + GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale), }; scheduler.Record([viewports](vk::CommandBuffer cmdbuf) { cmdbuf.SetViewport(0, viewports); }); } @@ -612,13 +623,29 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs if (!state_tracker.TouchScissors()) { return; } + u32 up_scale = 1; + u32 down_shift = 0; + if (texture_cache.IsRescaling()) { + up_scale = Settings::values.resolution_info.up_scale; + down_shift = Settings::values.resolution_info.down_shift; + } const std::array scissors{ - GetScissorState(regs, 0), GetScissorState(regs, 1), GetScissorState(regs, 2), - GetScissorState(regs, 3), GetScissorState(regs, 4), GetScissorState(regs, 5), - GetScissorState(regs, 6), GetScissorState(regs, 7), GetScissorState(regs, 8), - GetScissorState(regs, 9), GetScissorState(regs, 10), GetScissorState(regs, 11), - GetScissorState(regs, 12), GetScissorState(regs, 13), GetScissorState(regs, 14), - GetScissorState(regs, 15), + GetScissorState(regs, 0, up_scale, down_shift), + GetScissorState(regs, 1, up_scale, down_shift), + GetScissorState(regs, 2, up_scale, down_shift), + GetScissorState(regs, 3, up_scale, down_shift), + GetScissorState(regs, 4, up_scale, down_shift), + GetScissorState(regs, 5, up_scale, down_shift), + GetScissorState(regs, 6, up_scale, down_shift), + GetScissorState(regs, 7, up_scale, down_shift), + GetScissorState(regs, 8, up_scale, down_shift), + GetScissorState(regs, 9, up_scale, down_shift), + GetScissorState(regs, 10, up_scale, down_shift), + GetScissorState(regs, 11, up_scale, down_shift), + GetScissorState(regs, 12, up_scale, down_shift), + GetScissorState(regs, 13, up_scale, down_shift), + GetScissorState(regs, 14, up_scale, down_shift), + GetScissorState(regs, 15, up_scale, down_shift), }; scheduler.Record([scissors](vk::CommandBuffer cmdbuf) { cmdbuf.SetScissor(0, scissors); }); } diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index 2f2d6b31f..ac2bbebe0 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h @@ -71,11 +71,13 @@ public: } bool TouchViewports() { - return Exchange(Dirty::Viewports, false); + return Exchange(Dirty::Viewports, false) || + Exchange(VideoCommon::Dirty::RescaleViewports, false); } bool TouchScissors() { - return Exchange(Dirty::Scissors, false); + return Exchange(Dirty::Scissors, false) || + Exchange(VideoCommon::Dirty::RescaleScissors, false); } bool TouchDepthBias() { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index b7d1ae92d..4e5031acc 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -7,6 +7,7 @@ #include #include "common/alignment.h" +#include "common/settings.h" #include "video_core/dirty_flags.h" #include "video_core/engines/kepler_compute.h" #include "video_core/texture_cache/image_view_base.h" @@ -205,6 +206,7 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { return; } + bool rescaled; do { flags[Dirty::RenderTargets] = false; @@ -243,6 +245,7 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { check_rescale(render_targets.depth_buffer_id, tmp_depth_image); if (can_rescale) { + rescaled = true; const auto scale_up = [this](ImageId image_id) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; @@ -254,6 +257,7 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { } scale_up(tmp_depth_image); } else { + rescaled = false; const auto scale_down = [this](ImageId image_id) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; @@ -268,6 +272,12 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { } while (has_deleted_images); // Rescale End + if (is_rescaling != rescaled) { + flags[Dirty::RescaleViewports] = true; + flags[Dirty::RescaleScissors] = true; + is_rescaling = rescaled; + } + for (size_t index = 0; index < NUM_RT; ++index) { ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id)); @@ -279,9 +289,15 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { for (size_t index = 0; index < NUM_RT; ++index) { render_targets.draw_buffers[index] = static_cast(maxwell3d.regs.rt_control.Map(index)); } + u32 up_scale = 1; + u32 down_shift = 0; + if (is_rescaling) { + up_scale = Settings::values.resolution_info.up_scale; + down_shift = Settings::values.resolution_info.down_shift; + } render_targets.size = Extent2D{ - maxwell3d.regs.render_area.width, - maxwell3d.regs.render_area.height, + (maxwell3d.regs.render_area.width * up_scale) >> down_shift, + (maxwell3d.regs.render_area.height * up_scale) >> down_shift, }; flags[Dirty::DepthBiasGlobal] = true; @@ -538,6 +554,11 @@ void TextureCache

::PopAsyncFlushes() { committed_downloads.pop(); } +template +bool TextureCache

::IsRescaling() { + return is_rescaling; +} + template bool TextureCache

::IsRegionGpuModified(VAddr addr, size_t size) { bool is_modified = false; diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index cdd99242b..1f51fcee8 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -168,6 +168,8 @@ public: /// Return true when a CPU region is modified from the GPU [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); + [[nodiscard]] bool IsRescaling(); + std::mutex mutex; private: @@ -362,6 +364,7 @@ private: VAddr virtual_invalid_space{}; bool has_deleted_images = false; + bool is_rescaling = false; u64 total_used_memory = 0; u64 minimum_memory; u64 expected_memory; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 7ddc40b00..7ed833203 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -849,6 +849,8 @@ void Config::ReadRendererValues() { ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks); } + Settings::UpdateRescalingInfo(); + qt_config->endGroup(); } @@ -1402,6 +1404,8 @@ void Config::SaveRendererValues() { WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks); } + Settings::UpdateRescalingInfo(); + qt_config->endGroup(); } -- cgit v1.2.3 From 8704c939136e88876d65fc670bce98d8250a6588 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 20 Jul 2021 22:51:25 +0200 Subject: TextureCache: Fix rescaling of ImageCopies --- .../renderer_vulkan/vk_texture_cache.cpp | 40 +++++++++++++------- src/video_core/texture_cache/texture_cache.h | 43 ++++++++++++++++++++-- src/video_core/texture_cache/texture_cache_base.h | 2 +- 3 files changed, 67 insertions(+), 18 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 5fd190825..54236e87f 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -136,6 +136,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { if (info.type == ImageType::e3D) { flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; } + const auto scale_up = [&](u32 value) { return std::max((value * up) >> down, 1U); }; const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples); const bool is_2d = info.type == ImageType::e2D; return VkImageCreateInfo{ @@ -145,8 +146,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { .imageType = ConvertImageType(info.type), .format = format_info.format, .extent{ - .width = ((info.size.width * up) >> down) >> samples_x, - .height = (is_2d ? ((info.size.height * up) >> down) : info.size.height) >> samples_y, + .width = scale_up(info.size.width) >> samples_x, + .height = (is_2d ? scale_up(info.size.height) : info.size.height) >> samples_y, .depth = info.size.depth, }, .mipLevels = static_cast(info.resources.levels), @@ -1078,12 +1079,35 @@ bool Image::ScaleUp(bool save_as_backup) { MemoryCommit new_commit( runtime->memory_allocator.Commit(rescaled_image, MemoryUsage::DeviceLocal)); + SCOPE_EXIT({ + if (save_as_backup) { + backup_image = std::move(image); + backup_commit = std::move(commit); + has_backup = true; + } else { + runtime->prescaled_images.Push(std::move(image)); + runtime->prescaled_commits.Push(std::move(commit)); + } + image = std::move(rescaled_image); + commit = std::move(new_commit); + }); + + const PixelFormat format = StorageFormat(info.format); + const auto format_info = + MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, false, format); + const auto similar = runtime->device.GetSupportedFormat( + format_info.format, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT), + FormatType::Optimal); + + if (similar != format_info.format) { + return true; + } if (aspect_mask == 0) { aspect_mask = ImageAspectMask(info.format); } const auto scale_up = [&](u32 value) { - return (value * resolution.up_scale) >> resolution.down_shift; + return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); }; const bool is_2d = info.type == ImageType::e2D; @@ -1130,16 +1154,6 @@ bool Image::ScaleUp(bool save_as_backup) { vkRegions.push_back(blit); } BlitScale(*scheduler, *image, *rescaled_image, vkRegions, aspect_mask); - if (save_as_backup) { - backup_image = std::move(image); - backup_commit = std::move(commit); - has_backup = true; - } else { - runtime->prescaled_images.Push(std::move(image)); - runtime->prescaled_commits.Push(std::move(commit)); - } - image = std::move(rescaled_image); - commit = std::move(new_commit); return true; } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 4e5031acc..df697cdeb 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -929,8 +929,8 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA LOG_WARNING(HW_GPU, "Copying between images with different samples is not implemented"); } else { const SubresourceBase base = new_image.TryFindBase(overlap.gpu_addr).value(); - const auto copies = MakeShrinkImageCopies(new_info, overlap.info, base); - runtime.CopyImage(new_image, overlap, copies); + auto copies = MakeShrinkImageCopies(new_info, overlap.info, base); + runtime.CopyImage(new_image, overlap, std::move(copies)); } if (True(overlap.flags & ImageFlagBits::Tracked)) { UntrackImage(overlap, overlap_id); @@ -1569,9 +1569,33 @@ void TextureCache

::PrepareImageView(ImageViewId image_view_id, bool is_modifi } template -void TextureCache

::CopyImage(ImageId dst_id, ImageId src_id, std::span copies) { +void TextureCache

::CopyImage(ImageId dst_id, ImageId src_id, std::vector copies) { Image& dst = slot_images[dst_id]; Image& src = slot_images[src_id]; + const bool is_rescaled = True(src.flags & ImageFlagBits::Rescaled); + if (is_rescaled) { + ASSERT(True(dst.flags & ImageFlagBits::Rescaled)); + const bool both_2d{src.info.type == ImageType::e2D && dst.info.type == ImageType::e2D}; + const auto& resolution = Settings::values.resolution_info; + const auto scale_up = [&](u32 value) -> u32 { + if (value == 0) { + return 0U; + } + return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); + }; + for (auto& copy : copies) { + copy.src_offset.x = scale_up(copy.src_offset.x); + + copy.dst_offset.x = scale_up(copy.dst_offset.x); + + copy.extent.width = scale_up(copy.extent.width); + if (both_2d) { + copy.src_offset.y = scale_up(copy.src_offset.y); + copy.dst_offset.y = scale_up(copy.dst_offset.y); + copy.extent.height = scale_up(copy.extent.height); + } + } + } const auto dst_format_type = GetFormatType(dst.info.format); const auto src_format_type = GetFormatType(src.info.format); if (src_format_type == dst_format_type) { @@ -1639,10 +1663,21 @@ std::pair TextureCache

::RenderTargetFromImage( ImageId image_id, const ImageViewInfo& view_info) { const ImageViewId view_id = FindOrEmplaceImageView(image_id, view_info); const ImageBase& image = slot_images[image_id]; + const bool is_rescaled = True(image.flags & ImageFlagBits::Rescaled); const bool is_color = GetFormatType(image.info.format) == SurfaceType::ColorTexture; const ImageViewId color_view_id = is_color ? view_id : ImageViewId{}; const ImageViewId depth_view_id = is_color ? ImageViewId{} : view_id; - const Extent3D extent = MipSize(image.info.size, view_info.range.base.level); + Extent3D extent = MipSize(image.info.size, view_info.range.base.level); + if (is_rescaled) { + const auto& resolution = Settings::values.resolution_info; + const auto scale_up = [&](u32 value) { + return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); + }; + extent.width = scale_up(extent.width); + if (image.info.type == ImageType::e2D) { + extent.height = scale_up(extent.height); + } + } const u32 num_samples = image.info.num_samples; const auto [samples_x, samples_y] = SamplesLog2(num_samples); const FramebufferId framebuffer_id = GetFramebufferId(RenderTargets{ diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 1f51fcee8..deddf0d30 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -316,7 +316,7 @@ private: void PrepareImageView(ImageViewId image_view_id, bool is_modification, bool invalidate); /// Execute copies from one image to the other, even if they are incompatible - void CopyImage(ImageId dst_id, ImageId src_id, std::span copies); + void CopyImage(ImageId dst_id, ImageId src_id, std::vector copies); /// Bind an image view as render target, downloading resources preemtively if needed void BindRenderTarget(ImageViewId* old_id, ImageViewId new_id); -- cgit v1.2.3 From dfc65cd0a3b259588b47db1d32c827e7fc071aeb Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 21 Jul 2021 10:15:09 +0200 Subject: Texture Cache: Implement Rescaling on Aliases and Blits. --- src/video_core/texture_cache/texture_cache.h | 58 +++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 5 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index df697cdeb..25fea8240 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -437,8 +437,32 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, PrepareImage(src_id, false, false); PrepareImage(dst_id, true, false); - ImageBase& dst_image = slot_images[dst_id]; - const ImageBase& src_image = slot_images[src_id]; + Image& dst_image = slot_images[dst_id]; + const Image& src_image = slot_images[src_id]; + + const bool is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); + bool is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); + + if (is_src_rescaled && !is_dst_rescaled) { + if (ImageCanRescale(dst_image)) { + is_dst_rescaled = dst_image.ScaleUp(); + } + } + + const auto& resolution = Settings::values.resolution_info; + const auto scale_up = [&](u32 value) -> u32 { + if (value == 0) { + return 0U; + } + return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); + }; + + const auto scale_region = [&](Region2D& region) { + region.start.x = scale_up(region.start.x); + region.start.y = scale_up(region.start.y); + region.end.x = scale_up(region.end.x); + region.end.y = scale_up(region.end.y); + }; // TODO: Deduplicate const std::optional src_base = src_image.TryFindBase(src.Address()); @@ -446,20 +470,26 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); - const Region2D src_region{ + Region2D src_region{ Offset2D{.x = copy.src_x0 >> src_samples_x, .y = copy.src_y0 >> src_samples_y}, Offset2D{.x = copy.src_x1 >> src_samples_x, .y = copy.src_y1 >> src_samples_y}, }; + if (is_src_rescaled) { + scale_region(src_region); + } const std::optional dst_base = dst_image.TryFindBase(dst.Address()); const SubresourceRange dst_range{.base = dst_base.value(), .extent = {1, 1}}; const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); - const Region2D dst_region{ + Region2D dst_region{ Offset2D{.x = copy.dst_x0 >> dst_samples_x, .y = copy.dst_y0 >> dst_samples_y}, Offset2D{.x = copy.dst_x1 >> dst_samples_x, .y = copy.dst_y1 >> dst_samples_y}, }; + if (is_dst_rescaled) { + scale_region(dst_region); + } // Always call this after src_framebuffer_id was queried, as the address might be invalidated. Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; @@ -1514,18 +1544,28 @@ void TextureCache

::MarkModification(ImageBase& image) noexcept { template void TextureCache

::SynchronizeAliases(ImageId image_id) { boost::container::small_vector aliased_images; - ImageBase& image = slot_images[image_id]; + Image& image = slot_images[image_id]; + bool any_rescaled = True(image.flags & ImageFlagBits::Rescaled); u64 most_recent_tick = image.modification_tick; for (const AliasedImage& aliased : image.aliased_images) { ImageBase& aliased_image = slot_images[aliased.id]; if (image.modification_tick < aliased_image.modification_tick) { most_recent_tick = std::max(most_recent_tick, aliased_image.modification_tick); aliased_images.push_back(&aliased); + any_rescaled |= True(image.flags & ImageFlagBits::Rescaled); } } if (aliased_images.empty()) { return; } + const bool can_rescale = ImageCanRescale(image); + if (any_rescaled) { + if (can_rescale) { + ScaleUp(image); + } else { + ScaleDown(image); + } + } image.modification_tick = most_recent_tick; std::ranges::sort(aliased_images, [this](const AliasedImage* lhs, const AliasedImage* rhs) { const ImageBase& lhs_image = slot_images[lhs->id]; @@ -1533,6 +1573,14 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { return lhs_image.modification_tick < rhs_image.modification_tick; }); for (const AliasedImage* const aliased : aliased_images) { + if (any_rescaled) { + Image& aliased_image = slot_images[aliased->id]; + if (can_rescale) { + ScaleUp(aliased_image); + } else { + ScaleDown(aliased_image); + } + } CopyImage(image_id, aliased->id, aliased->copies); } } -- cgit v1.2.3 From d5143c83a9eacf23cc66616bcd1a1b0ccfda5082 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Thu, 22 Jul 2021 00:16:19 -0400 Subject: texture_cache: Fix typo in aliased image rescaling --- src/video_core/texture_cache/texture_cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 25fea8240..179f37526 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1552,7 +1552,7 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { if (image.modification_tick < aliased_image.modification_tick) { most_recent_tick = std::max(most_recent_tick, aliased_image.modification_tick); aliased_images.push_back(&aliased); - any_rescaled |= True(image.flags & ImageFlagBits::Rescaled); + any_rescaled |= True(aliased_image.flags & ImageFlagBits::Rescaled); } } if (aliased_images.empty()) { -- cgit v1.2.3 From 74efa57c1b78b4a07ad0003e847bd5f0aa7c7bb5 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 25 Jul 2021 21:44:13 -0300 Subject: texture_cache: Add image getters --- src/video_core/texture_cache/texture_cache.h | 10 ++++++++++ src/video_core/texture_cache/texture_cache_base.h | 6 ++++++ 2 files changed, 16 insertions(+) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 179f37526..ae74a6ecf 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -119,6 +119,16 @@ typename P::ImageView& TextureCache

::GetImageView(ImageViewId id) noexcept { return slot_image_views[id]; } +template +const typename P::Image& TextureCache

::GetImage(ImageId id) const noexcept { + return slot_images[id]; +} + +template +typename P::Image& TextureCache

::GetImage(ImageId id) noexcept { + return slot_images[id]; +} + template void TextureCache

::MarkModification(ImageId id) noexcept { MarkModification(slot_images[id]); diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index deddf0d30..0d2d9ec2e 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -95,6 +95,12 @@ public: /// Return a reference to the given image view id [[nodiscard]] ImageView& GetImageView(ImageViewId id) noexcept; + /// Return a constant reference to the given image id + [[nodiscard]] const Image& GetImage(ImageId id) const noexcept; + + /// Return a reference to the given image id + [[nodiscard]] Image& GetImage(ImageId id) noexcept; + /// Mark an image as modified from the GPU void MarkModification(ImageId id) noexcept; -- cgit v1.2.3 From 0e8cf38f392f2ea6f7f5195070ad721b78590c04 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 26 Jul 2021 09:33:00 +0200 Subject: Texture Cache: Implement Blacklisting. --- .../renderer_vulkan/vk_compute_pipeline.cpp | 29 ++++++++++++++++-- .../renderer_vulkan/vk_graphics_pipeline.cpp | 28 +++++++++++++++++- src/video_core/texture_cache/image_base.h | 1 + src/video_core/texture_cache/texture_cache.h | 34 +++++++++++++++++++++- src/video_core/texture_cache/texture_cache_base.h | 2 ++ 5 files changed, 90 insertions(+), 4 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index bda75788c..5c591e345 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -111,6 +111,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, std::array image_view_ids; boost::container::static_vector image_view_indices; boost::container::static_vector samplers; + boost::container::static_vector image_view_blacklist; const auto& qmd{kepler_compute.launch_description}; const auto& cbufs{qmd.const_buffer_config}; @@ -151,10 +152,34 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, samplers.push_back(sampler->Handle()); } } - std::ranges::for_each(info.image_descriptors, add_image); + const u32 black_list_base = image_view_indices.size(); + bool atleast_one_blacklisted = false; + for (const auto& desc : info.image_descriptors) { + const bool is_black_listed = + desc.is_written && (desc.type == Shader::TextureType::Color2D || + desc.type == Shader::TextureType::ColorArray2D); + for (u32 index = 0; index < desc.count; ++index) { + image_view_blacklist.push_back(is_black_listed); + } + atleast_one_blacklisted |= is_black_listed; + add_image(desc); + } const std::span indices_span(image_view_indices.data(), image_view_indices.size()); - texture_cache.FillComputeImageViews(indices_span, image_view_ids); + bool has_listed_stuffs; + do { + has_listed_stuffs = false; + texture_cache.FillComputeImageViews(indices_span, image_view_ids); + if (atleast_one_blacklisted) { + for (u32 index = 0; index < image_view_blacklist.size(); index++) { + if (image_view_blacklist[index]) { + ImageView& image_view{ + texture_cache.GetImageView(image_view_ids[index + black_list_base])}; + has_listed_stuffs |= texture_cache.BlackListImage(image_view.image_id); + } + } + } + } while (has_listed_stuffs); buffer_cache.UnbindComputeTextureBuffers(); ImageId* texture_buffer_ids{image_view_ids.data()}; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 967762c37..4d966ee4b 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -280,6 +280,7 @@ template void GraphicsPipeline::ConfigureImpl(bool is_indexed) { std::array image_view_ids; std::array image_view_indices; + std::array image_view_blacklist; std::array samplers; size_t sampler_index{}; size_t image_index{}; @@ -290,6 +291,8 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { const auto& regs{maxwell3d.regs}; const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; + u32 start_black_list = std::numeric_limits::max(); + u32 end_black_list = 0; const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE { const Shader::Info& info{stage_infos[stage]}; buffer_cache.UnbindGraphicsStorageBuffers(stage); @@ -350,6 +353,15 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { } if constexpr (Spec::has_images) { for (const auto& desc : info.image_descriptors) { + if (desc.is_written && (desc.type == Shader::TextureType::Color2D || + desc.type == Shader::TextureType::ColorArray2D)) { + auto index_copy = image_index; + for (u32 index = 0; index < desc.count; ++index) { + start_black_list = std::min(start_black_list, index_copy); + image_view_blacklist[index_copy++] = true; + end_black_list = std::max(end_black_list, index_copy); + } + } add_image(desc); } } @@ -370,7 +382,21 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { config_stage(4); } const std::span indices_span(image_view_indices.data(), image_index); - texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); + bool has_listed_stuffs; + do { + has_listed_stuffs = false; + texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); + if constexpr (Spec::has_images) { + if (start_black_list < end_black_list) { + for (u32 index = start_black_list; index < end_black_list; index++) { + if (image_view_blacklist[index]) { + ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])}; + has_listed_stuffs |= texture_cache.BlackListImage(image_view.image_id); + } + } + } + } + } while (has_listed_stuffs); ImageId* texture_buffer_index{image_view_ids.data()}; const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE { diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 1cd30fd37..10dd52e28 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -37,6 +37,7 @@ enum class ImageFlagBits : u32 { // Rescaler Rescaled = 1 << 12, RescaleChecked = 1 << 13, + Blacklisted = 1 << 14, }; DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index ae74a6ecf..ce5994d5f 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -227,6 +227,7 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { flags[Dirty::RenderTargetControl] = false; bool can_rescale = true; + bool any_blacklisted = false; std::array tmp_color_images{}; ImageId tmp_depth_image{}; const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { @@ -236,6 +237,7 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { id_save = image_id; auto& image = slot_images[image_id]; can_rescale &= ImageCanRescale(image); + any_blacklisted |= True(image.flags & ImageFlagBits::Blacklisted); } else { id_save = CORRUPT_ID; } @@ -268,10 +270,13 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { scale_up(tmp_depth_image); } else { rescaled = false; - const auto scale_down = [this](ImageId image_id) { + const auto scale_down = [this, any_blacklisted](ImageId image_id) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; ScaleDown(image); + if (any_blacklisted) { + image.flags |= ImageFlagBits::Blacklisted; + } } }; for (size_t index = 0; index < NUM_RT; ++index) { @@ -736,8 +741,22 @@ ImageId TextureCache

::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, return image_id; } +template +bool TextureCache

::BlackListImage(ImageId image_id) { + auto& image = slot_images[image_id]; + if (True(image.flags & ImageFlagBits::Blacklisted)) { + return false; + } + image.flags |= ImageFlagBits::Blacklisted; + ScaleDown(image); + return true; +} + template bool TextureCache

::ImageCanRescale(Image& image) { + if (True(image.flags & ImageFlagBits::Blacklisted)) { + return false; + } if (True(image.flags & ImageFlagBits::Rescaled) || True(image.flags & ImageFlagBits::RescaleChecked)) { return true; @@ -912,6 +931,7 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA bool can_rescale = (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; bool any_rescaled = false; + bool any_blacklisted = false; for (const ImageId sibling_id : all_siblings) { if (!can_rescale) { break; @@ -919,6 +939,7 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA Image& sibling = slot_images[sibling_id]; can_rescale &= ImageCanRescale(sibling); any_rescaled |= True(sibling.flags & ImageFlagBits::Rescaled); + any_blacklisted |= True(sibling.flags & ImageFlagBits::Blacklisted); } can_rescale &= any_rescaled; @@ -932,6 +953,9 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA for (const ImageId sibling_id : all_siblings) { Image& sibling = slot_images[sibling_id]; ScaleDown(sibling); + if (any_blacklisted) { + sibling.flags |= ImageFlagBits::Blacklisted; + } } } @@ -1556,6 +1580,7 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { boost::container::small_vector aliased_images; Image& image = slot_images[image_id]; bool any_rescaled = True(image.flags & ImageFlagBits::Rescaled); + bool any_blacklisted = True(image.flags & ImageFlagBits::Blacklisted); u64 most_recent_tick = image.modification_tick; for (const AliasedImage& aliased : image.aliased_images) { ImageBase& aliased_image = slot_images[aliased.id]; @@ -1563,6 +1588,7 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { most_recent_tick = std::max(most_recent_tick, aliased_image.modification_tick); aliased_images.push_back(&aliased); any_rescaled |= True(aliased_image.flags & ImageFlagBits::Rescaled); + any_blacklisted |= True(aliased_image.flags & ImageFlagBits::Blacklisted); } } if (aliased_images.empty()) { @@ -1574,6 +1600,9 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { ScaleUp(image); } else { ScaleDown(image); + if (any_blacklisted) { + image.flags |= ImageFlagBits::Blacklisted; + } } } image.modification_tick = most_recent_tick; @@ -1589,6 +1618,9 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { ScaleUp(aliased_image); } else { ScaleDown(aliased_image); + if (any_blacklisted) { + aliased_image.flags |= ImageFlagBits::Blacklisted; + } } } CopyImage(image_id, aliased->id, aliased->copies); diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 0d2d9ec2e..35a29cd9b 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -176,6 +176,8 @@ public: [[nodiscard]] bool IsRescaling(); + [[nodiscard]] bool BlackListImage(ImageId image_id); + std::mutex mutex; private: -- cgit v1.2.3 From 07c564f38b238af9be7a9d8aee1149a353c2880b Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 27 Jul 2021 01:29:55 +0200 Subject: Texture Cache: Implement Rating System. --- src/video_core/texture_cache/image_base.cpp | 6 ++-- src/video_core/texture_cache/image_base.h | 2 ++ src/video_core/texture_cache/image_info.cpp | 11 ++++++++ src/video_core/texture_cache/image_info.h | 1 + src/video_core/texture_cache/texture_cache.h | 42 ++++++++++++++++++++-------- 5 files changed, 47 insertions(+), 15 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/image_base.cpp b/src/video_core/texture_cache/image_base.cpp index 6052d148a..e9e725edf 100644 --- a/src/video_core/texture_cache/image_base.cpp +++ b/src/video_core/texture_cache/image_base.cpp @@ -60,9 +60,9 @@ namespace { ImageBase::ImageBase(const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_) : info{info_}, guest_size_bytes{CalculateGuestSizeInBytes(info)}, unswizzled_size_bytes{CalculateUnswizzledSizeBytes(info)}, - converted_size_bytes{CalculateConvertedSizeBytes(info)}, gpu_addr{gpu_addr_}, - cpu_addr{cpu_addr_}, cpu_addr_end{cpu_addr + guest_size_bytes}, - mip_level_offsets{CalculateMipLevelOffsets(info)} { + converted_size_bytes{CalculateConvertedSizeBytes(info)}, scale_rating{}, + scale_tick{}, gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, + cpu_addr_end{cpu_addr + guest_size_bytes}, mip_level_offsets{CalculateMipLevelOffsets(info)} { if (info.type == ImageType::e3D) { slice_offsets = CalculateSliceOffsets(info); slice_subresources = CalculateSliceSubresources(info); diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 10dd52e28..97f107b4d 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -78,6 +78,8 @@ struct ImageBase { u32 guest_size_bytes = 0; u32 unswizzled_size_bytes = 0; u32 converted_size_bytes = 0; + u32 scale_rating = 0; + u64 scale_tick = 0; ImageFlagBits flags = ImageFlagBits::CpuModified; GPUVAddr gpu_addr = 0; diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 022ca9033..7fa8fd4fe 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -31,6 +31,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { .depth = config.block_depth, }; } + rescaleable = false; tile_width_spacing = config.tile_width_spacing; if (config.texture_type != TextureType::Texture2D && config.texture_type != TextureType::Texture2DNoMipmap) { @@ -53,12 +54,14 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { case TextureType::Texture2DNoMipmap: ASSERT(config.Depth() == 1); type = config.IsPitchLinear() ? ImageType::Linear : ImageType::e2D; + rescaleable = !config.IsPitchLinear(); size.width = config.Width(); size.height = config.Height(); resources.layers = config.BaseLayer() + 1; break; case TextureType::Texture2DArray: type = ImageType::e2D; + rescaleable = true; size.width = config.Width(); size.height = config.Height(); resources.layers = config.BaseLayer() + config.Depth(); @@ -98,12 +101,14 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { // FIXME: Call this without passing *this layer_stride = CalculateLayerStride(*this); maybe_unaligned_layer_stride = CalculateLayerSize(*this); + rescaleable &= (block.depth == 0) && resources.levels == 1; } } ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept { const auto& rt = regs.rt[index]; format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(rt.format); + rescaleable = false; if (rt.tile_mode.is_pitch_linear) { ASSERT(rt.tile_mode.is_3d == 0); type = ImageType::Linear; @@ -129,6 +134,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) type = ImageType::e3D; size.depth = rt.depth; } else { + rescaleable = block.depth == 0 && size.height > 256; type = ImageType::e2D; resources.layers = rt.depth; } @@ -138,6 +144,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept { format = VideoCore::Surface::PixelFormatFromDepthFormat(regs.zeta.format); size.width = regs.zeta_width; size.height = regs.zeta_height; + rescaleable = false; resources.levels = 1; layer_stride = regs.zeta.layer_stride * 4; maybe_unaligned_layer_stride = layer_stride; @@ -156,6 +163,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept { type = ImageType::e3D; size.depth = regs.zeta_depth; } else { + rescaleable = block.depth == 0 && size.height > 256; type = ImageType::e2D; resources.layers = regs.zeta_depth; } @@ -164,6 +172,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept { ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { UNIMPLEMENTED_IF_MSG(config.layer != 0, "Surface layer is not zero"); format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(config.format); + rescaleable = false; if (config.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch) { type = ImageType::Linear; size = Extent3D{ @@ -174,6 +183,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { pitch = config.pitch; } else { type = config.block_depth > 0 ? ImageType::e3D : ImageType::e2D; + block = Extent3D{ .width = config.block_width, .height = config.block_height, @@ -186,6 +196,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { .height = config.height, .depth = 1, }; + rescaleable = block.depth == 0 && size.height > 256; } } diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 16d4cee37..e874d2870 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -33,6 +33,7 @@ struct ImageInfo { u32 maybe_unaligned_layer_stride = 0; u32 num_samples = 1; u32 tile_width_spacing = 0; + bool rescaleable = false; }; } // namespace VideoCommon diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index ce5994d5f..be40f6b88 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -216,7 +216,10 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { return; } + u32 scale_rating; bool rescaled; + std::array tmp_color_images{}; + ImageId tmp_depth_image{}; do { flags[Dirty::RenderTargets] = false; @@ -226,10 +229,10 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { const bool force = flags[Dirty::RenderTargetControl]; flags[Dirty::RenderTargetControl] = false; + scale_rating = 0; + bool any_rescaled = false; bool can_rescale = true; bool any_blacklisted = false; - std::array tmp_color_images{}; - ImageId tmp_depth_image{}; const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { if (view_id) { const auto& view = slot_image_views[view_id]; @@ -238,6 +241,10 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { auto& image = slot_images[image_id]; can_rescale &= ImageCanRescale(image); any_blacklisted |= True(image.flags & ImageFlagBits::Blacklisted); + any_rescaled |= True(image.flags & ImageFlagBits::Rescaled); + scale_rating = std::max(scale_rating, image.scale_tick <= frame_tick + ? image.scale_rating + 1U + : image.scale_rating); } else { id_save = CORRUPT_ID; } @@ -257,17 +264,19 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { check_rescale(render_targets.depth_buffer_id, tmp_depth_image); if (can_rescale) { - rescaled = true; + rescaled = any_rescaled || scale_rating >= 2; const auto scale_up = [this](ImageId image_id) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; ScaleUp(image); } }; - for (size_t index = 0; index < NUM_RT; ++index) { - scale_up(tmp_color_images[index]); + if (rescaled) { + for (size_t index = 0; index < NUM_RT; ++index) { + scale_up(tmp_color_images[index]); + } + scale_up(tmp_depth_image); } - scale_up(tmp_depth_image); } else { rescaled = false; const auto scale_down = [this, any_blacklisted](ImageId image_id) { @@ -283,10 +292,23 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { scale_down(tmp_color_images[index]); } scale_down(tmp_depth_image); + scale_rating = 0; } } while (has_deleted_images); // Rescale End + const auto set_rating = [this, scale_rating](ImageId image_id) { + if (image_id != CORRUPT_ID) { + Image& image = slot_images[image_id]; + image.scale_rating = scale_rating; + image.scale_tick = frame_tick + 1; + } + }; + for (size_t index = 0; index < NUM_RT; ++index) { + set_rating(tmp_color_images[index]); + } + set_rating(tmp_depth_image); + if (is_rescaling != rescaled) { flags[Dirty::RescaleViewports] = true; flags[Dirty::RescaleScissors] = true; @@ -761,10 +783,7 @@ bool TextureCache

::ImageCanRescale(Image& image) { True(image.flags & ImageFlagBits::RescaleChecked)) { return true; } - const auto& info = image.info; - const bool can_this_rescale = - (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; - if (!can_this_rescale) { + if (!image.info.rescaleable) { image.flags &= ~ImageFlagBits::RescaleChecked; return false; } @@ -928,8 +947,7 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA }; ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu); - bool can_rescale = - (info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0; + bool can_rescale = info.rescaleable; bool any_rescaled = false; bool any_blacklisted = false; for (const ImageId sibling_id : all_siblings) { -- cgit v1.2.3 From 56ccda1d9952368d0c1e29d7c4b486c547de9549 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 28 Jul 2021 02:47:06 -0300 Subject: texture_cache: Simplify image view queries and blacklisting --- .../renderer_opengl/gl_compute_pipeline.cpp | 36 +++++++------ .../renderer_opengl/gl_graphics_pipeline.cpp | 42 +++++++-------- .../renderer_opengl/gl_texture_cache.cpp | 10 ++-- src/video_core/renderer_opengl/gl_texture_cache.h | 5 +- src/video_core/renderer_vulkan/pipeline_helper.h | 19 ++++--- .../renderer_vulkan/vk_compute_pipeline.cpp | 60 ++++++++-------------- .../renderer_vulkan/vk_graphics_pipeline.cpp | 54 +++++-------------- .../renderer_vulkan/vk_texture_cache.cpp | 22 +++++--- src/video_core/renderer_vulkan/vk_texture_cache.h | 41 +++++++++------ src/video_core/texture_cache/image_base.cpp | 2 + src/video_core/texture_cache/image_base.h | 3 ++ src/video_core/texture_cache/image_view_base.cpp | 2 +- src/video_core/texture_cache/image_view_base.h | 4 +- src/video_core/texture_cache/texture_cache.h | 47 +++++++++-------- src/video_core/texture_cache/texture_cache_base.h | 30 ++++++----- src/video_core/texture_cache/types.h | 7 +++ 16 files changed, 192 insertions(+), 192 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 19c8ca7b2..ab2baefbb 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp @@ -79,8 +79,7 @@ void ComputePipeline::Configure() { } texture_cache.SynchronizeComputeDescriptors(); - std::array image_view_ids; - boost::container::static_vector image_view_indices; + boost::container::static_vector views; std::array samplers; std::array textures; std::array images; @@ -110,33 +109,39 @@ void ComputePipeline::Configure() { } return TexturePair(gpu_memory.Read(addr), via_header_index); }}; - const auto add_image{[&](const auto& desc) { + const auto add_image{[&](const auto& desc, bool blacklist) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices.push_back(handle.first); + views.push_back({ + .index = handle.first, + .blacklist = blacklist, + .id = {}, + }); } }}; for (const auto& desc : info.texture_buffer_descriptors) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices.push_back(handle.first); + views.push_back({handle.first}); samplers[sampler_binding++] = 0; } } - std::ranges::for_each(info.image_buffer_descriptors, add_image); + for (const auto& desc : info.image_buffer_descriptors) { + add_image(desc, false); + } for (const auto& desc : info.texture_descriptors) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices.push_back(handle.first); + views.push_back({handle.first}); Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); samplers[sampler_binding++] = sampler->Handle(); } } - std::ranges::for_each(info.image_descriptors, add_image); - - const std::span indices_span(image_view_indices.data(), image_view_indices.size()); - texture_cache.FillComputeImageViews(indices_span, image_view_ids); + for (const auto& desc : info.image_descriptors) { + add_image(desc, true); + } + texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); if (assembly_program.handle != 0) { program_manager.BindComputeAssemblyProgram(assembly_program.handle); @@ -152,7 +157,7 @@ void ComputePipeline::Configure() { if constexpr (is_image) { is_written = desc.is_written; } - ImageView& image_view{texture_cache.GetImageView(image_view_ids[texbuf_index])}; + ImageView& image_view{texture_cache.GetImageView(views[texbuf_index].id)}; buffer_cache.BindComputeTextureBuffer(texbuf_index, image_view.GpuAddr(), image_view.BufferSize(), image_view.format, is_written, is_image); @@ -168,19 +173,20 @@ void ComputePipeline::Configure() { buffer_cache.runtime.SetImagePointers(textures.data(), images.data()); buffer_cache.BindHostComputeBuffers(); - const ImageId* views_it{image_view_ids.data() + num_texture_buffers + num_image_buffers}; + const VideoCommon::ImageViewInOut* views_it{views.data() + num_texture_buffers + + num_image_buffers}; texture_binding += num_texture_buffers; image_binding += num_image_buffers; for (const auto& desc : info.texture_descriptors) { for (u32 index = 0; index < desc.count; ++index) { - ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; + ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; textures[texture_binding++] = image_view.Handle(desc.type); } } for (const auto& desc : info.image_descriptors) { for (u32 index = 0; index < desc.count; ++index) { - ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; + ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; if (desc.is_written) { texture_cache.MarkModification(image_view.image_id); } diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 43ab5c03b..0bbda7951 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -15,7 +15,7 @@ #include "video_core/renderer_opengl/gl_shader_util.h" #include "video_core/renderer_opengl/gl_state_tracker.h" #include "video_core/shader_notify.h" -#include "video_core/texture_cache/texture_cache_base.h" +#include "video_core/texture_cache/texture_cache.h" #if defined(_MSC_VER) && defined(NDEBUG) #define LAMBDA_FORCEINLINE [[msvc::forceinline]] @@ -280,10 +280,9 @@ GraphicsPipeline::GraphicsPipeline( template void GraphicsPipeline::ConfigureImpl(bool is_indexed) { - std::array image_view_ids; - std::array image_view_indices; + std::array views; std::array samplers; - size_t image_view_index{}; + size_t views_index{}; GLsizei sampler_binding{}; texture_cache.SynchronizeGraphicsDescriptors(); @@ -328,30 +327,34 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { } return TexturePair(gpu_memory.Read(addr), via_header_index); }}; - const auto add_image{[&](const auto& desc) { + const auto add_image{[&](const auto& desc, bool blacklist) LAMBDA_FORCEINLINE { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices[image_view_index++] = handle.first; + views[views_index++] = { + .index = handle.first, + .blacklist = blacklist, + .id = {}, + }; } }}; if constexpr (Spec::has_texture_buffers) { for (const auto& desc : info.texture_buffer_descriptors) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices[image_view_index++] = handle.first; + views[views_index++] = {handle.first}; samplers[sampler_binding++] = 0; } } } if constexpr (Spec::has_image_buffers) { for (const auto& desc : info.image_buffer_descriptors) { - add_image(desc); + add_image(desc, false); } } for (const auto& desc : info.texture_descriptors) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices[image_view_index++] = handle.first; + views[views_index++] = {handle.first}; Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; samplers[sampler_binding++] = sampler->Handle(); @@ -359,7 +362,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { } if constexpr (Spec::has_images) { for (const auto& desc : info.image_descriptors) { - add_image(desc); + add_image(desc, true); } } }}; @@ -378,13 +381,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { if constexpr (Spec::enabled_stages[4]) { config_stage(4); } - const std::span indices_span(image_view_indices.data(), image_view_index); - texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); + texture_cache.FillGraphicsImageViews(std::span(views.data(), views_index)); texture_cache.UpdateRenderTargets(false); state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle()); - ImageId* texture_buffer_index{image_view_ids.data()}; + VideoCommon::ImageViewInOut* texture_buffer_it{views.data()}; const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE { size_t index{}; const auto add_buffer{[&](const auto& desc) { @@ -394,12 +396,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { if constexpr (is_image) { is_written = desc.is_written; } - ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)}; + ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)}; buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(), image_view.BufferSize(), image_view.format, is_written, is_image); ++index; - ++texture_buffer_index; + ++texture_buffer_it; } }}; const Shader::Info& info{stage_infos[stage]}; @@ -415,9 +417,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { add_buffer(desc); } } - texture_buffer_index += Shader::NumDescriptors(info.texture_descriptors); + texture_buffer_it += Shader::NumDescriptors(info.texture_descriptors); if constexpr (Spec::has_images) { - texture_buffer_index += Shader::NumDescriptors(info.image_descriptors); + texture_buffer_it += Shader::NumDescriptors(info.image_descriptors); } }}; if constexpr (Spec::enabled_stages[0]) { @@ -446,7 +448,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { } else { program_manager.BindSourcePrograms(source_programs); } - const ImageId* views_it{image_view_ids.data()}; + const VideoCommon::ImageViewInOut* views_it{views.data()}; GLsizei texture_binding = 0; GLsizei image_binding = 0; std::array textures; @@ -464,13 +466,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { const auto& info{stage_infos[stage]}; for (const auto& desc : info.texture_descriptors) { for (u32 index = 0; index < desc.count; ++index) { - ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; + ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; textures[texture_binding++] = image_view.Handle(desc.type); } } for (const auto& desc : info.image_descriptors) { for (u32 index = 0; index < desc.count; ++index) { - ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; + ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; if (desc.is_written) { texture_cache.MarkModification(image_view.image_id); } diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 5e2695576..5d14bfc97 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -472,11 +472,7 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& set_view(Shader::TextureType::ColorArray1D, null_image_1d_array.handle); set_view(Shader::TextureType::ColorArray2D, null_image_view_2d_array.handle); set_view(Shader::TextureType::ColorArrayCube, null_image_cube_array.handle); -} - -TextureCacheRuntime::~TextureCacheRuntime() = default; -void TextureCacheRuntime::Init() { resolution = Settings::values.resolution_info; is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0; if (is_rescaling_on) { @@ -485,6 +481,8 @@ void TextureCacheRuntime::Init() { } } +TextureCacheRuntime::~TextureCacheRuntime() = default; + void TextureCacheRuntime::Finish() { glFinish(); } @@ -685,6 +683,8 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, } } +Image::Image(const VideoCommon::NullImageParams& params) : VideoCommon::ImageBase{params} {} + Image::~Image() = default; void Image::UploadMemory(const ImageBufferMap& map, @@ -1076,7 +1076,7 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, const VideoCommon::ImageViewInfo& view_info) : VideoCommon::ImageViewBase{info, view_info} {} -ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) +ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params) : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} GLuint ImageView::StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format) { diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 787b63e87..e76ec522a 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -73,8 +73,6 @@ public: StateTracker& state_tracker); ~TextureCacheRuntime(); - void Init(); - void Finish(); ImageBufferMap UploadStagingBuffer(size_t size); @@ -167,6 +165,7 @@ class Image : public VideoCommon::ImageBase { public: explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); + explicit Image(const VideoCommon::NullImageParams&); ~Image(); @@ -223,7 +222,7 @@ public: const VideoCommon::ImageViewInfo&, GPUVAddr); explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, const VideoCommon::ImageViewInfo& view_info); - explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); + explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); [[nodiscard]] GLuint StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format); diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index 7ba6078df..bf18b34d1 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h @@ -156,28 +156,27 @@ private: u32 texture_bit{1u}; }; -inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers, - const ImageId*& image_view_ids, TextureCache& texture_cache, +inline void PushImageDescriptors(TextureCache& texture_cache, VKUpdateDescriptorQueue& update_descriptor_queue, - RescalingPushConstant& rescaling) { - static constexpr VideoCommon::ImageViewId NULL_IMAGE_VIEW_ID{0}; - image_view_ids += Shader::NumDescriptors(info.texture_buffer_descriptors); - image_view_ids += Shader::NumDescriptors(info.image_buffer_descriptors); + const Shader::Info& info, RescalingPushConstant& rescaling, + const VkSampler*& samplers, + const VideoCommon::ImageViewInOut*& views) { + views += Shader::NumDescriptors(info.texture_buffer_descriptors); + views += Shader::NumDescriptors(info.image_buffer_descriptors); for (const auto& desc : info.texture_descriptors) { for (u32 index = 0; index < desc.count; ++index) { - const VideoCommon::ImageViewId image_view_id{*(image_view_ids++)}; + const VideoCommon::ImageViewId image_view_id{(views++)->id}; const VkSampler sampler{*(samplers++)}; ImageView& image_view{texture_cache.GetImageView(image_view_id)}; const Image& image{texture_cache.GetImage(image_view.image_id)}; const VkImageView vk_image_view{image_view.Handle(desc.type)}; update_descriptor_queue.AddSampledImage(vk_image_view, sampler); - rescaling.PushTexture(image_view_id != NULL_IMAGE_VIEW_ID && - True(image.flags & VideoCommon::ImageFlagBits::Rescaled)); + rescaling.PushTexture(True(image.flags & VideoCommon::ImageFlagBits::Rescaled)); } } for (const auto& desc : info.image_descriptors) { for (u32 index = 0; index < desc.count; ++index) { - ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; + ImageView& image_view{texture_cache.GetImageView((views++)->id)}; if (desc.is_written) { texture_cache.MarkModification(image_view.image_id); } diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 5c591e345..f89b84c6e 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -108,10 +108,8 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, texture_cache.SynchronizeComputeDescriptors(); static constexpr size_t max_elements = 64; - std::array image_view_ids; - boost::container::static_vector image_view_indices; + boost::container::static_vector views; boost::container::static_vector samplers; - boost::container::static_vector image_view_blacklist; const auto& qmd{kepler_compute.launch_description}; const auto& cbufs{qmd.const_buffer_config}; @@ -135,54 +133,37 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, } return TexturePair(gpu_memory.Read(addr), via_header_index); }}; - const auto add_image{[&](const auto& desc) { + const auto add_image{[&](const auto& desc, bool blacklist) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices.push_back(handle.first); + views.push_back({ + .index = handle.first, + .blacklist = blacklist, + .id = {}, + }); } }}; - std::ranges::for_each(info.texture_buffer_descriptors, add_image); - std::ranges::for_each(info.image_buffer_descriptors, add_image); + for (const auto& desc : info.texture_buffer_descriptors) { + add_image(desc, false); + } + for (const auto& desc : info.image_buffer_descriptors) { + add_image(desc, false); + } for (const auto& desc : info.texture_descriptors) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices.push_back(handle.first); + views.push_back({handle.first}); Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); samplers.push_back(sampler->Handle()); } } - const u32 black_list_base = image_view_indices.size(); - bool atleast_one_blacklisted = false; for (const auto& desc : info.image_descriptors) { - const bool is_black_listed = - desc.is_written && (desc.type == Shader::TextureType::Color2D || - desc.type == Shader::TextureType::ColorArray2D); - for (u32 index = 0; index < desc.count; ++index) { - image_view_blacklist.push_back(is_black_listed); - } - atleast_one_blacklisted |= is_black_listed; - add_image(desc); + add_image(desc, true); } - - const std::span indices_span(image_view_indices.data(), image_view_indices.size()); - bool has_listed_stuffs; - do { - has_listed_stuffs = false; - texture_cache.FillComputeImageViews(indices_span, image_view_ids); - if (atleast_one_blacklisted) { - for (u32 index = 0; index < image_view_blacklist.size(); index++) { - if (image_view_blacklist[index]) { - ImageView& image_view{ - texture_cache.GetImageView(image_view_ids[index + black_list_base])}; - has_listed_stuffs |= texture_cache.BlackListImage(image_view.image_id); - } - } - } - } while (has_listed_stuffs); + texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); buffer_cache.UnbindComputeTextureBuffers(); - ImageId* texture_buffer_ids{image_view_ids.data()}; size_t index{}; const auto add_buffer{[&](const auto& desc) { constexpr bool is_image = std::is_same_v; @@ -191,11 +172,10 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, if constexpr (is_image) { is_written = desc.is_written; } - ImageView& image_view = texture_cache.GetImageView(*texture_buffer_ids); + ImageView& image_view = texture_cache.GetImageView(views[index].id); buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(), image_view.BufferSize(), image_view.format, is_written, is_image); - ++texture_buffer_ids; ++index; } }}; @@ -207,9 +187,9 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, RescalingPushConstant rescaling(num_textures); const VkSampler* samplers_it{samplers.data()}; - const ImageId* views_it{image_view_ids.data()}; - PushImageDescriptors(info, samplers_it, views_it, texture_cache, update_descriptor_queue, - rescaling); + const VideoCommon::ImageViewInOut* views_it{views.data()}; + PushImageDescriptors(texture_cache, update_descriptor_queue, info, rescaling, samplers_it, + views_it); if (!is_built.load(std::memory_order::relaxed)) { // Wait for the pipeline to be built diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 4d966ee4b..4efb5d735 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -278,12 +278,10 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) { template void GraphicsPipeline::ConfigureImpl(bool is_indexed) { - std::array image_view_ids; - std::array image_view_indices; - std::array image_view_blacklist; + std::array views; std::array samplers; size_t sampler_index{}; - size_t image_index{}; + size_t view_index{}; texture_cache.SynchronizeGraphicsDescriptors(); @@ -291,8 +289,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { const auto& regs{maxwell3d.regs}; const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; - u32 start_black_list = std::numeric_limits::max(); - u32 end_black_list = 0; const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE { const Shader::Info& info{stage_infos[stage]}; buffer_cache.UnbindGraphicsStorageBuffers(stage); @@ -329,7 +325,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { const auto add_image{[&](const auto& desc) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices[image_index++] = handle.first; + views[view_index++] = {handle.first}; } }}; if constexpr (Spec::has_texture_buffers) { @@ -345,7 +341,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { for (const auto& desc : info.texture_descriptors) { for (u32 index = 0; index < desc.count; ++index) { const auto handle{read_handle(desc, index)}; - image_view_indices[image_index++] = handle.first; + views[view_index++] = {handle.first}; Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; samplers[sampler_index++] = sampler->Handle(); @@ -353,15 +349,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { } if constexpr (Spec::has_images) { for (const auto& desc : info.image_descriptors) { - if (desc.is_written && (desc.type == Shader::TextureType::Color2D || - desc.type == Shader::TextureType::ColorArray2D)) { - auto index_copy = image_index; - for (u32 index = 0; index < desc.count; ++index) { - start_black_list = std::min(start_black_list, index_copy); - image_view_blacklist[index_copy++] = true; - end_black_list = std::max(end_black_list, index_copy); - } - } add_image(desc); } } @@ -381,24 +368,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { if constexpr (Spec::enabled_stages[4]) { config_stage(4); } - const std::span indices_span(image_view_indices.data(), image_index); - bool has_listed_stuffs; - do { - has_listed_stuffs = false; - texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); - if constexpr (Spec::has_images) { - if (start_black_list < end_black_list) { - for (u32 index = start_black_list; index < end_black_list; index++) { - if (image_view_blacklist[index]) { - ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])}; - has_listed_stuffs |= texture_cache.BlackListImage(image_view.image_id); - } - } - } - } - } while (has_listed_stuffs); + texture_cache.FillGraphicsImageViews(std::span(views.data(), view_index)); - ImageId* texture_buffer_index{image_view_ids.data()}; + VideoCommon::ImageViewInOut* texture_buffer_it{views.data()}; const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE { size_t index{}; const auto add_buffer{[&](const auto& desc) { @@ -408,12 +380,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { if constexpr (is_image) { is_written = desc.is_written; } - ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)}; + ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)}; buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(), image_view.BufferSize(), image_view.format, is_written, is_image); ++index; - ++texture_buffer_index; + ++texture_buffer_it; } }}; buffer_cache.UnbindGraphicsTextureBuffers(stage); @@ -429,9 +401,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { add_buffer(desc); } } - texture_buffer_index += Shader::NumDescriptors(info.texture_descriptors); + texture_buffer_it += Shader::NumDescriptors(info.texture_descriptors); if constexpr (Spec::has_images) { - texture_buffer_index += Shader::NumDescriptors(info.image_descriptors); + texture_buffer_it += Shader::NumDescriptors(info.image_descriptors); } }}; if constexpr (Spec::enabled_stages[0]) { @@ -457,11 +429,11 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { RescalingPushConstant rescaling(num_textures); const VkSampler* samplers_it{samplers.data()}; - const ImageId* views_it{image_view_ids.data()}; + const VideoCommon::ImageViewInOut* views_it{views.data()}; const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { buffer_cache.BindHostStageBuffers(stage); - PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache, - update_descriptor_queue, rescaling); + PushImageDescriptors(texture_cache, update_descriptor_queue, stage_infos[stage], rescaling, + samplers_it, views_it); }}; if constexpr (Spec::enabled_stages[0]) { prepare_stage(0); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index b21992fce..3400066a6 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -730,10 +730,17 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con } } // Anonymous namespace -void TextureCacheRuntime::Init() { - resolution = Settings::values.resolution_info; - is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0; -} +TextureCacheRuntime::TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_, + MemoryAllocator& memory_allocator_, + StagingBufferPool& staging_buffer_pool_, + BlitImageHelper& blit_image_helper_, + ASTCDecoderPass& astc_decoder_pass_, + RenderPassCache& render_pass_cache_) + : device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_}, + staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_}, + astc_decoder_pass{astc_decoder_pass_}, render_pass_cache{render_pass_cache_}, + resolution{Settings::values.resolution_info}, + is_rescaling_on(resolution.up_scale != 1 || resolution.down_shift != 0) {} void TextureCacheRuntime::Finish() { scheduler.Finish(); @@ -1040,6 +1047,8 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu } } +Image::Image(const VideoCommon::NullImageParams& params) : VideoCommon::ImageBase{params} {} + Image::~Image() = default; void Image::UploadMemory(const StagingBufferRef& map, std::span copies) { @@ -1187,8 +1196,7 @@ bool Image::ScaleDown(bool save_as_backup) { }*/ const auto& resolution = runtime->resolution; - vk::Image downscaled_image = - MakeImage(runtime->device, info); + vk::Image downscaled_image = MakeImage(runtime->device, info); MemoryCommit new_commit( runtime->memory_allocator.Commit(downscaled_image, MemoryUsage::DeviceLocal)); @@ -1301,7 +1309,7 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_}, buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {} -ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params) +ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams& params) : VideoCommon::ImageViewBase{params} {} VkImageView ImageView::DepthView() { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 958a64651..9c39a6d99 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -34,21 +34,16 @@ class RenderPassCache; class StagingBufferPool; class VKScheduler; -struct TextureCacheRuntime { - const Device& device; - VKScheduler& scheduler; - MemoryAllocator& memory_allocator; - StagingBufferPool& staging_buffer_pool; - BlitImageHelper& blit_image_helper; - ASTCDecoderPass& astc_decoder_pass; - RenderPassCache& render_pass_cache; +class TextureCacheRuntime { +public: static constexpr size_t TICKS_TO_DESTROY = 6; - DelayedDestructionRing prescaled_images; - DelayedDestructionRing prescaled_commits; - Settings::ResolutionScalingInfo resolution; - bool is_rescaling_on{}; - void Init(); + explicit TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_, + MemoryAllocator& memory_allocator_, + StagingBufferPool& staging_buffer_pool_, + BlitImageHelper& blit_image_helper_, + ASTCDecoderPass& astc_decoder_pass_, + RenderPassCache& render_pass_cache_); void Finish(); @@ -56,6 +51,10 @@ struct TextureCacheRuntime { StagingBufferRef DownloadStagingBuffer(size_t size); + void TickFrame(); + + u64 GetDeviceLocalMemory() const; + void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, const Region2D& dst_region, const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, @@ -84,15 +83,25 @@ struct TextureCacheRuntime { return true; } - void TickFrame(); + const Device& device; + VKScheduler& scheduler; + MemoryAllocator& memory_allocator; + StagingBufferPool& staging_buffer_pool; + BlitImageHelper& blit_image_helper; + ASTCDecoderPass& astc_decoder_pass; + RenderPassCache& render_pass_cache; - u64 GetDeviceLocalMemory() const; + DelayedDestructionRing prescaled_images; + DelayedDestructionRing prescaled_commits; + Settings::ResolutionScalingInfo resolution; + bool is_rescaling_on{}; }; class Image : public VideoCommon::ImageBase { public: explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); + explicit Image(const VideoCommon::NullImageParams&); ~Image(); @@ -151,7 +160,7 @@ public: explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&, const VideoCommon::ImageViewInfo&, GPUVAddr); - explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); + explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); [[nodiscard]] VkImageView DepthView(); diff --git a/src/video_core/texture_cache/image_base.cpp b/src/video_core/texture_cache/image_base.cpp index e9e725edf..25a211df8 100644 --- a/src/video_core/texture_cache/image_base.cpp +++ b/src/video_core/texture_cache/image_base.cpp @@ -69,6 +69,8 @@ ImageBase::ImageBase(const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_ } } +ImageBase::ImageBase(const NullImageParams&) {} + ImageMapView::ImageMapView(GPUVAddr gpu_addr_, VAddr cpu_addr_, size_t size_, ImageId image_id_) : gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, size{size_}, image_id{image_id_} {} diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 97f107b4d..9c34687e0 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -48,8 +48,11 @@ struct AliasedImage { ImageId id; }; +struct NullImageParams {}; + struct ImageBase { explicit ImageBase(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); + explicit ImageBase(const NullImageParams&); [[nodiscard]] std::optional TryFindBase(GPUVAddr other_addr) const noexcept; diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index 450becbeb..e66dc9320 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp @@ -45,6 +45,6 @@ ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_in ASSERT_MSG(view_info.type == ImageViewType::Buffer, "Expected texture buffer"); } -ImageViewBase::ImageViewBase(const NullImageParams&) {} +ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {} } // namespace VideoCommon diff --git a/src/video_core/texture_cache/image_view_base.h b/src/video_core/texture_cache/image_view_base.h index 903f715c5..9c24c5359 100644 --- a/src/video_core/texture_cache/image_view_base.h +++ b/src/video_core/texture_cache/image_view_base.h @@ -15,7 +15,7 @@ using VideoCore::Surface::PixelFormat; struct ImageViewInfo; struct ImageInfo; -struct NullImageParams {}; +struct NullImageViewParams {}; enum class ImageViewFlagBits : u16 { PreemtiveDownload = 1 << 0, @@ -28,7 +28,7 @@ struct ImageViewBase { explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info, ImageId image_id); explicit ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info); - explicit ImageViewBase(const NullImageParams&); + explicit ImageViewBase(const NullImageViewParams&); [[nodiscard]] bool IsBuffer() const noexcept { return type == ImageViewType::Buffer; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index be40f6b88..4e97a9e6a 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -36,7 +36,6 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& Tegra::MemoryManager& gpu_memory_) : runtime{runtime_}, rasterizer{rasterizer_}, maxwell3d{maxwell3d_}, kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_} { - runtime.Init(); // Configure null sampler TSCEntry sampler_descriptor{}; sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); @@ -46,7 +45,8 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& // Make sure the first index is reserved for the null resources // This way the null resource becomes a compile time constant - void(slot_image_views.insert(runtime, NullImageParams{})); + void(slot_images.insert(NullImageParams{})); + void(slot_image_views.insert(runtime, NullImageViewParams{})); void(slot_samplers.insert(runtime, sampler_descriptor)); if constexpr (HAS_DEVICE_MEMORY_INFO) { @@ -57,7 +57,7 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY); minimum_memory = 0; } else { - // on OGL we can be more conservatives as the driver takes care. + // On OpenGL we can be more conservatives as the driver takes care. expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB; critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB; minimum_memory = expected_memory; @@ -135,15 +135,14 @@ void TextureCache

::MarkModification(ImageId id) noexcept { } template -void TextureCache

::FillGraphicsImageViews(std::span indices, - std::span image_view_ids) { - FillImageViews(graphics_image_table, graphics_image_view_ids, indices, image_view_ids); +template +void TextureCache

::FillGraphicsImageViews(std::span views) { + FillImageViews(graphics_image_table, graphics_image_view_ids, views); } template -void TextureCache

::FillComputeImageViews(std::span indices, - std::span image_view_ids) { - FillImageViews(compute_image_table, compute_image_view_ids, indices, image_view_ids); +void TextureCache

::FillComputeImageViews(std::span views) { + FillImageViews(compute_image_table, compute_image_view_ids, views); } template @@ -346,17 +345,26 @@ typename P::Framebuffer* TextureCache

::GetFramebuffer() { } template +template void TextureCache

::FillImageViews(DescriptorTable& table, std::span cached_image_view_ids, - std::span indices, - std::span image_view_ids) { - ASSERT(indices.size() <= image_view_ids.size()); + std::span views) { + bool has_blacklisted; do { has_deleted_images = false; - std::ranges::transform(indices, image_view_ids.begin(), [&](u32 index) { - return VisitImageView(table, cached_image_view_ids, index); - }); - } while (has_deleted_images); + if constexpr (has_blacklists) { + has_blacklisted = false; + } + for (ImageViewInOut& view : views) { + view.id = VisitImageView(table, cached_image_view_ids, view.index); + if constexpr (has_blacklists) { + if (view.blacklist && view.id != NULL_IMAGE_VIEW_ID) { + const ImageViewBase& image_view{slot_image_views[view.id]}; + has_blacklisted |= BlackListImage(image_view.image_id); + } + } + } + } while (has_deleted_images || (has_blacklists && has_blacklisted)); } template @@ -622,7 +630,7 @@ void TextureCache

::PopAsyncFlushes() { } template -bool TextureCache

::IsRescaling() { +bool TextureCache

::IsRescaling() const noexcept { return is_rescaling; } @@ -775,12 +783,11 @@ bool TextureCache

::BlackListImage(ImageId image_id) { } template -bool TextureCache

::ImageCanRescale(Image& image) { +bool TextureCache

::ImageCanRescale(ImageBase& image) { if (True(image.flags & ImageFlagBits::Blacklisted)) { return false; } - if (True(image.flags & ImageFlagBits::Rescaled) || - True(image.flags & ImageFlagBits::RescaleChecked)) { + if (True(image.flags & (ImageFlagBits::Rescaled | ImageFlagBits::RescaleChecked))) { return true; } if (!image.info.rescaleable) { diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 35a29cd9b..b6cc09682 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -39,6 +39,16 @@ using VideoCore::Surface::PixelFormatFromDepthFormat; using VideoCore::Surface::PixelFormatFromRenderTargetFormat; using namespace Common::Literals; +struct ImageViewInOut { + u32 index; + bool blacklist; + union { + struct Empty { + } empty{}; + ImageViewId id; + }; +}; + template class TextureCache { /// Address shift for caching images into a hash table @@ -53,11 +63,6 @@ class TextureCache { /// 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; - /// Image view ID for null descriptors - static constexpr ImageViewId NULL_IMAGE_VIEW_ID{0}; - /// Sampler ID for bugged sampler ids - static constexpr SamplerId NULL_SAMPLER_ID{0}; - static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; @@ -105,11 +110,11 @@ public: void MarkModification(ImageId id) noexcept; /// Fill image_view_ids with the graphics images in indices - void FillGraphicsImageViews(std::span indices, - std::span image_view_ids); + template + void FillGraphicsImageViews(std::span views); /// Fill image_view_ids with the compute images in indices - void FillComputeImageViews(std::span indices, std::span image_view_ids); + void FillComputeImageViews(std::span views); /// Get the sampler from the graphics descriptor table in the specified index Sampler* GetGraphicsSampler(u32 index); @@ -174,7 +179,7 @@ public: /// Return true when a CPU region is modified from the GPU [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); - [[nodiscard]] bool IsRescaling(); + [[nodiscard]] bool IsRescaling() const noexcept; [[nodiscard]] bool BlackListImage(ImageId image_id); @@ -216,9 +221,10 @@ private: void RunGarbageCollector(); /// Fills image_view_ids in the image views in indices + template void FillImageViews(DescriptorTable& table, - std::span cached_image_view_ids, std::span indices, - std::span image_view_ids); + std::span cached_image_view_ids, + std::span views); /// Find or create an image view in the guest descriptor table ImageViewId VisitImageView(DescriptorTable& table, @@ -336,7 +342,7 @@ private: /// Returns true if the current clear parameters clear the whole image of a given image view [[nodiscard]] bool IsFullClear(ImageViewId id); - bool ImageCanRescale(Image& image); + bool ImageCanRescale(ImageBase& image); void InvalidateScale(Image& image); bool ScaleUp(Image& image); bool ScaleDown(Image& image); diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 47a11cb2f..5c274abdf 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h @@ -22,6 +22,13 @@ using ImageAllocId = SlotId; using SamplerId = SlotId; using FramebufferId = SlotId; +/// Fake image ID for null image views +constexpr ImageId NULL_IMAGE_ID{0}; +/// Image view ID for null descriptors +constexpr ImageViewId NULL_IMAGE_VIEW_ID{0}; +/// Sampler ID for bugged sampler ids +constexpr SamplerId NULL_SAMPLER_ID{0}; + enum class ImageType : u32 { e1D, e2D, -- cgit v1.2.3 From 2182d2575010a5a85c99c09c6a1c57962242444d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 28 Jul 2021 02:53:24 -0300 Subject: texture_cache: Fix blacklists on compute --- src/video_core/texture_cache/texture_cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 4e97a9e6a..4dbded635 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -142,7 +142,7 @@ void TextureCache

::FillGraphicsImageViews(std::span views) { template void TextureCache

::FillComputeImageViews(std::span views) { - FillImageViews(compute_image_table, compute_image_view_ids, views); + FillImageViews(compute_image_table, compute_image_view_ids, views); } template -- cgit v1.2.3 From c7a1cbad44487b2c5f9da31ce6d3c76b7dec4f05 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 31 Jul 2021 17:42:37 -0300 Subject: texture_cache: Add getter to query if image view is rescaled --- src/video_core/renderer_opengl/gl_compute_pipeline.cpp | 3 +-- src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | 3 +-- src/video_core/renderer_vulkan/pipeline_helper.h | 3 +-- src/video_core/texture_cache/texture_cache.h | 16 ++++++---------- src/video_core/texture_cache/texture_cache_base.h | 9 +++------ 5 files changed, 12 insertions(+), 22 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 12093c3c4..02853b078 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp @@ -186,8 +186,7 @@ void ComputePipeline::Configure() { for (u32 index = 0; index < desc.count; ++index) { ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; textures[texture_binding] = image_view.Handle(desc.type); - if (True(texture_cache.GetImage(image_view.image_id).flags & - VideoCommon::ImageFlagBits::Rescaled)) { + if (texture_cache.IsRescaling(image_view)) { scaling_mask |= 1u << texture_binding; } ++texture_binding; diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 01aa2897a..c3d549a6e 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -472,8 +472,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { for (u32 index = 0; index < desc.count; ++index) { ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; textures[texture_binding] = image_view.Handle(desc.type); - if (True(texture_cache.GetImage(image_view.image_id).flags & - VideoCommon::ImageFlagBits::Rescaled)) { + if (texture_cache.IsRescaling(image_view)) { scaling_mask |= 1u << stage_texture_binding; } ++texture_binding; diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index bf18b34d1..bce4220c6 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h @@ -168,10 +168,9 @@ inline void PushImageDescriptors(TextureCache& texture_cache, const VideoCommon::ImageViewId image_view_id{(views++)->id}; const VkSampler sampler{*(samplers++)}; ImageView& image_view{texture_cache.GetImageView(image_view_id)}; - const Image& image{texture_cache.GetImage(image_view.image_id)}; const VkImageView vk_image_view{image_view.Handle(desc.type)}; update_descriptor_queue.AddSampledImage(vk_image_view, sampler); - rescaling.PushTexture(True(image.flags & VideoCommon::ImageFlagBits::Rescaled)); + rescaling.PushTexture(texture_cache.IsRescaling(image_view)); } } for (const auto& desc : info.image_descriptors) { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 4dbded635..0e70c4db2 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -119,16 +119,6 @@ typename P::ImageView& TextureCache

::GetImageView(ImageViewId id) noexcept { return slot_image_views[id]; } -template -const typename P::Image& TextureCache

::GetImage(ImageId id) const noexcept { - return slot_images[id]; -} - -template -typename P::Image& TextureCache

::GetImage(ImageId id) noexcept { - return slot_images[id]; -} - template void TextureCache

::MarkModification(ImageId id) noexcept { MarkModification(slot_images[id]); @@ -634,6 +624,12 @@ bool TextureCache

::IsRescaling() const noexcept { return is_rescaling; } +template +bool TextureCache

::IsRescaling(const ImageViewBase& image_view) const noexcept { + const ImageBase& image = slot_images[image_view.image_id]; + return True(image.flags & ImageFlagBits::Rescaled); +} + template bool TextureCache

::IsRegionGpuModified(VAddr addr, size_t size) { bool is_modified = false; diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index b6cc09682..8b417b611 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -21,6 +21,7 @@ #include "video_core/texture_cache/descriptor_table.h" #include "video_core/texture_cache/image_base.h" #include "video_core/texture_cache/image_info.h" +#include "video_core/texture_cache/image_view_base.h" #include "video_core/texture_cache/image_view_info.h" #include "video_core/texture_cache/render_targets.h" #include "video_core/texture_cache/slot_vector.h" @@ -100,12 +101,6 @@ public: /// Return a reference to the given image view id [[nodiscard]] ImageView& GetImageView(ImageViewId id) noexcept; - /// Return a constant reference to the given image id - [[nodiscard]] const Image& GetImage(ImageId id) const noexcept; - - /// Return a reference to the given image id - [[nodiscard]] Image& GetImage(ImageId id) noexcept; - /// Mark an image as modified from the GPU void MarkModification(ImageId id) noexcept; @@ -181,6 +176,8 @@ public: [[nodiscard]] bool IsRescaling() const noexcept; + [[nodiscard]] bool IsRescaling(const ImageViewBase& image_view) const noexcept; + [[nodiscard]] bool BlackListImage(ImageId image_id); std::mutex mutex; -- cgit v1.2.3 From ed675cfd8cc89d64c763becfd991d1dd40deac5a Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Wed, 4 Aug 2021 19:02:30 -0400 Subject: texture_cache: Disable dst_image scaling in BlitImage Fixes scaling in Super Mario Party --- src/video_core/texture_cache/texture_cache.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 0e70c4db2..d86f80b5d 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -478,11 +478,13 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, const bool is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); bool is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); - if (is_src_rescaled && !is_dst_rescaled) { - if (ImageCanRescale(dst_image)) { - is_dst_rescaled = dst_image.ScaleUp(); - } - } + // TODO: This requires the rendertarget image views to be updated with the upscaled sizes, + // otherwise the blit will use a larger framebuffer size than the image view attachment. + // if (is_src_rescaled && !is_dst_rescaled) { + // if (ImageCanRescale(dst_image)) { + // is_dst_rescaled = dst_image.ScaleUp(); + // } + // } const auto& resolution = Settings::values.resolution_info; const auto scale_up = [&](u32 value) -> u32 { -- cgit v1.2.3 From 4b1393a691d1d8d79c57e7b73734cb8287b91760 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 7 Aug 2021 02:15:24 +0200 Subject: Texture Cache: Correctly fix Blits Rescaling. --- src/video_core/texture_cache/texture_cache.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index d86f80b5d..2de439889 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -473,18 +473,21 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, PrepareImage(dst_id, true, false); Image& dst_image = slot_images[dst_id]; - const Image& src_image = slot_images[src_id]; + Image& src_image = slot_images[src_id]; - const bool is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); + bool is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); bool is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); - // TODO: This requires the rendertarget image views to be updated with the upscaled sizes, - // otherwise the blit will use a larger framebuffer size than the image view attachment. - // if (is_src_rescaled && !is_dst_rescaled) { - // if (ImageCanRescale(dst_image)) { - // is_dst_rescaled = dst_image.ScaleUp(); - // } - // } + if (is_src_rescaled != is_dst_rescaled) { + if (ImageCanRescale(dst_image)) { + ScaleUp(dst_image); + is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); + } + if (ImageCanRescale(src_image)) { + ScaleUp(src_image); + is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); + } + } const auto& resolution = Settings::values.resolution_info; const auto scale_up = [&](u32 value) -> u32 { -- cgit v1.2.3 From d7c97921696486a95aaaf5c805b9fcc12230de77 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 7 Aug 2021 04:32:17 +0200 Subject: TextureCache: Fix Buffer Views Scaling. --- src/video_core/texture_cache/image_view_base.cpp | 11 ++++++----- src/video_core/texture_cache/texture_cache.h | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index e66dc9320..c7b4fc231 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp @@ -37,11 +37,12 @@ ImageViewBase::ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_i } ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info) - : format{info.format}, type{ImageViewType::Buffer}, size{ - .width = info.size.width, - .height = 1, - .depth = 1, - } { + : image_id{NULL_IMAGE_ID}, format{info.format}, type{ImageViewType::Buffer}, + size{ + .width = info.size.width, + .height = 1, + .depth = 1, + } { ASSERT_MSG(view_info.type == ImageViewType::Buffer, "Expected texture buffer"); } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 2de439889..764984546 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -631,6 +631,9 @@ bool TextureCache

::IsRescaling() const noexcept { template bool TextureCache

::IsRescaling(const ImageViewBase& image_view) const noexcept { + if (image_view.type == ImageViewType::Buffer) { + return false; + } const ImageBase& image = slot_images[image_view.image_id]; return True(image.flags & ImageFlagBits::Rescaled); } -- cgit v1.2.3 From 68e038404cc0069d9f59068a60b56e67b4321e7a Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 14 Aug 2021 00:01:47 -0400 Subject: shader, video_core: Fix GCC build errors --- src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 4 ---- src/video_core/renderer_opengl/gl_compute_pipeline.cpp | 3 --- src/video_core/texture_cache/texture_cache_base.h | 10 +++------- 3 files changed, 3 insertions(+), 14 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 519ce8b9b..4d168a96d 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -243,10 +243,6 @@ Id IsScaled(EmitContext& ctx, const IR::Value& index, Id member_index, u32 base_ if (base_index != 0) { index_value = ctx.OpIAdd(ctx.U32[1], index_value, ctx.Const(base_index)); } - const Id word_index{ctx.OpShiftRightArithmetic(ctx.U32[1], index_value, ctx.Const(5u))}; - const Id pointer{ctx.OpAccessChain(push_constant_u32, ctx.rescaling_push_constants, - member_index, word_index)}; - const Id word{ctx.OpLoad(ctx.U32[1], pointer)}; const Id bit_index{ctx.OpBitwiseAnd(ctx.U32[1], index_value, ctx.Const(31u))}; bit = ctx.OpBitFieldUExtract(ctx.U32[1], index_value, bit_index, ctx.Const(1u)); } diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 9af61c340..5c1f21c65 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp @@ -143,9 +143,6 @@ void ComputePipeline::Configure() { } texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); - const bool is_rescaling{texture_cache.IsRescaling()}; - const f32 config_down_factor{Settings::values.resolution_info.down_factor}; - const f32 down_factor{is_rescaling ? config_down_factor : 1.0f}; if (assembly_program.handle != 0) { program_manager.BindComputeAssemblyProgram(assembly_program.handle); } else { diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 8b417b611..517a4c224 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -41,13 +41,9 @@ using VideoCore::Surface::PixelFormatFromRenderTargetFormat; using namespace Common::Literals; struct ImageViewInOut { - u32 index; - bool blacklist; - union { - struct Empty { - } empty{}; - ImageViewId id; - }; + u32 index{}; + bool blacklist{}; + ImageViewId id{}; }; template -- cgit v1.2.3 From 6000fe69a4b2805a48ce045d9a383fda27d5e57b Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 14 Sep 2021 00:45:50 -0400 Subject: image_info: Mark MSAA textures as non-rescalable Blitting or resolving multisampled images requires the dimensions of the src and dst to be equal for valid usage, making them difficult for resolution scaling using the current implementation. --- src/video_core/texture_cache/image_info.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 7fa8fd4fe..bdf306bf9 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -101,7 +101,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { // FIXME: Call this without passing *this layer_stride = CalculateLayerStride(*this); maybe_unaligned_layer_stride = CalculateLayerSize(*this); - rescaleable &= (block.depth == 0) && resources.levels == 1; + rescaleable &= (block.depth == 0) && resources.levels == 1 && num_samples == 1; } } @@ -134,7 +134,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) type = ImageType::e3D; size.depth = rt.depth; } else { - rescaleable = block.depth == 0 && size.height > 256; + rescaleable = block.depth == 0 && size.height > 256 && num_samples == 1; type = ImageType::e2D; resources.layers = rt.depth; } -- cgit v1.2.3 From 19ca0c9ab5cbaa86e30743ea760e0aab5c40c1d6 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 20 Sep 2021 19:11:03 +0200 Subject: TextureCache: Base fixes on rescaling. --- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 3 ++- src/video_core/texture_cache/texture_cache.h | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 87f265e09..1ceffa718 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -207,7 +207,7 @@ void RasterizerVulkan::Clear() { query_cache.UpdateCounters(); - const auto& regs = maxwell3d.regs; + auto& regs = maxwell3d.regs; const bool use_color = regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || regs.clear_buffers.A; const bool use_depth = regs.clear_buffers.Z; @@ -228,6 +228,7 @@ void RasterizerVulkan::Clear() { up_scale = Settings::values.resolution_info.up_scale; down_shift = Settings::values.resolution_info.down_shift; } + UpdateViewportsState(regs); VkClearRect clear_rect{ .rect = GetScissorState(regs, 0, up_scale, down_shift), diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 764984546..a543776fd 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -205,8 +205,8 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { return; } - u32 scale_rating; - bool rescaled; + u32 scale_rating = 0; + bool rescaled = false; std::array tmp_color_images{}; ImageId tmp_depth_image{}; do { @@ -223,7 +223,7 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { bool can_rescale = true; bool any_blacklisted = false; const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { - if (view_id) { + if (view_id != NULL_IMAGE_VIEW_ID && view_id != ImageViewId{}) { const auto& view = slot_image_views[view_id]; const auto image_id = view.image_id; id_save = image_id; @@ -265,6 +265,7 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { scale_up(tmp_color_images[index]); } scale_up(tmp_depth_image); + scale_rating = 2; } } else { rescaled = false; -- cgit v1.2.3 From ea82bd4b7e4c4f23a40f8a35858d8b74950fc347 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 20 Sep 2021 22:18:15 +0200 Subject: Texture Cache: Fix Rescaling on Multisample --- src/video_core/renderer_vulkan/vk_texture_cache.cpp | 8 ++++++-- src/video_core/texture_cache/image_info.cpp | 4 ++-- src/video_core/texture_cache/texture_cache.h | 17 +++++++++++++---- 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 5b4f51a31..4f0bab274 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -860,9 +860,10 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, nullptr, nullptr, read_barriers); if (is_resolve) { + VkImageResolve resolve_info = + MakeImageResolve(dst_region, src_region, dst_layers, src_layers); cmdbuf.ResolveImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - MakeImageResolve(dst_region, src_region, dst_layers, src_layers)); + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, resolve_info); } else { const bool is_linear = filter == Fermi2D::Filter::Bilinear; const VkFilter vk_filter = is_linear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; @@ -1149,6 +1150,9 @@ bool Image::ScaleUp() { if (aspect_mask == 0) { aspect_mask = ImageAspectMask(info.format); } + if (info.num_samples > 1) { + return true; + } const PixelFormat format = StorageFormat(info.format); const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format); const auto similar = device.GetSupportedFormat( diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index bdf306bf9..7fa8fd4fe 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -101,7 +101,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { // FIXME: Call this without passing *this layer_stride = CalculateLayerStride(*this); maybe_unaligned_layer_stride = CalculateLayerSize(*this); - rescaleable &= (block.depth == 0) && resources.levels == 1 && num_samples == 1; + rescaleable &= (block.depth == 0) && resources.levels == 1; } } @@ -134,7 +134,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) type = ImageType::e3D; size.depth = rt.depth; } else { - rescaleable = block.depth == 0 && size.height > 256 && num_samples == 1; + rescaleable = block.depth == 0 && size.height > 256; type = ImageType::e2D; resources.layers = rt.depth; } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index a543776fd..b60f840c1 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -476,17 +476,26 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, Image& dst_image = slot_images[dst_id]; Image& src_image = slot_images[src_id]; + bool is_resolve = src_image.info.num_samples != 1 && dst_image.info.num_samples == 1; + bool is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); bool is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); if (is_src_rescaled != is_dst_rescaled) { - if (ImageCanRescale(dst_image)) { - ScaleUp(dst_image); - is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); - } if (ImageCanRescale(src_image)) { ScaleUp(src_image); is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); + if (is_resolve) { + dst_image.info.rescaleable = true; + for (const auto& alias : dst_image.aliased_images) { + Image& other_image = slot_images[alias.id]; + other_image.info.rescaleable = true; + } + } + } + if (ImageCanRescale(dst_image)) { + ScaleUp(dst_image); + is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); } } -- cgit v1.2.3 From 237a43004fb27a273495a0b44515cf7389dea553 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 3 Oct 2021 22:42:29 +0200 Subject: Texture Cache: Fix calculations when scaling. --- src/video_core/texture_cache/texture_cache.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index b60f840c1..691198853 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -858,6 +858,12 @@ bool TextureCache

::ScaleUp(Image& image) { if (!rescaled) { return false; } + const auto& add_to_size = Settings::values.resolution_info.up_factor - 1.0f; + const auto sign = std::signbit(add_to_size); + const u64 tentative_size = static_cast( + std::max(image.guest_size_bytes, image.unswizzled_size_bytes) * std::abs(add_to_size)); + const u64 fitted_size = Common::AlignUp(tentative_size, 1024); + total_used_memory += sign ? -fitted_size : fitted_size; InvalidateScale(image); return true; } @@ -868,6 +874,12 @@ bool TextureCache

::ScaleDown(Image& image) { if (!rescaled) { return false; } + const auto& add_to_size = Settings::values.resolution_info.up_factor - 1.0f; + const auto sign = std::signbit(add_to_size); + const u64 tentative_size = static_cast( + std::max(image.guest_size_bytes, image.unswizzled_size_bytes) * std::abs(add_to_size)); + const u64 fitted_size = Common::AlignUp(tentative_size, 1024); + total_used_memory += sign ? fitted_size : -fitted_size; InvalidateScale(image); return true; } -- cgit v1.2.3 From 88ef04dbaf26ab83ec85bfa3c68434c283c66e50 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 5 Oct 2021 00:07:51 -0400 Subject: texture_cache: Refactor scaled image size calculation --- src/video_core/texture_cache/texture_cache.h | 24 +++++++++++------------ src/video_core/texture_cache/texture_cache_base.h | 1 + 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 691198853..b708e41b5 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -852,18 +852,23 @@ void TextureCache

::InvalidateScale(Image& image) { has_deleted_images = true; } +template +u64 TextureCache

::GetScaledImageSizeBytes(Image& image) { + const f32 add_to_size = Settings::values.resolution_info.up_factor - 1.0f; + const bool sign = std::signbit(add_to_size); + const u32 image_size_bytes = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); + const u64 tentative_size = static_cast(image_size_bytes * std::abs(add_to_size)); + const u64 fitted_size = Common::AlignUp(tentative_size, 1024); + return sign ? -fitted_size : fitted_size; +} + template bool TextureCache

::ScaleUp(Image& image) { const bool rescaled = image.ScaleUp(); if (!rescaled) { return false; } - const auto& add_to_size = Settings::values.resolution_info.up_factor - 1.0f; - const auto sign = std::signbit(add_to_size); - const u64 tentative_size = static_cast( - std::max(image.guest_size_bytes, image.unswizzled_size_bytes) * std::abs(add_to_size)); - const u64 fitted_size = Common::AlignUp(tentative_size, 1024); - total_used_memory += sign ? -fitted_size : fitted_size; + total_used_memory += GetScaledImageSizeBytes(image); InvalidateScale(image); return true; } @@ -874,12 +879,7 @@ bool TextureCache

::ScaleDown(Image& image) { if (!rescaled) { return false; } - const auto& add_to_size = Settings::values.resolution_info.up_factor - 1.0f; - const auto sign = std::signbit(add_to_size); - const u64 tentative_size = static_cast( - std::max(image.guest_size_bytes, image.unswizzled_size_bytes) * std::abs(add_to_size)); - const u64 fitted_size = Common::AlignUp(tentative_size, 1024); - total_used_memory += sign ? fitted_size : -fitted_size; + total_used_memory += GetScaledImageSizeBytes(image); InvalidateScale(image); return true; } diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 517a4c224..40e003b60 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -339,6 +339,7 @@ private: void InvalidateScale(Image& image); bool ScaleUp(Image& image); bool ScaleDown(Image& image); + u64 GetScaledImageSizeBytes(Image& image); Runtime& runtime; VideoCore::RasterizerInterface& rasterizer; -- cgit v1.2.3 From 31478c6c1b841b9a820742830b136775fafe270f Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:18:00 -0400 Subject: video_core: Misc resolution scaling related refactoring --- src/common/settings.cpp | 2 +- src/video_core/renderer_opengl/gl_rasterizer.cpp | 4 +-- .../renderer_opengl/gl_texture_cache.cpp | 31 +++++++++------------- src/video_core/renderer_opengl/gl_texture_cache.h | 11 +++++--- src/video_core/renderer_vulkan/vk_state_tracker.h | 10 ++++--- .../renderer_vulkan/vk_texture_cache.cpp | 31 +++++++++++++--------- src/video_core/renderer_vulkan/vk_texture_cache.h | 7 +++-- src/video_core/texture_cache/texture_cache.h | 2 -- 8 files changed, 51 insertions(+), 47 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index f0686a7c5..12fdb0f9b 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -107,7 +107,7 @@ float Volume() { } void UpdateRescalingInfo() { - auto setup = values.resolution_setup.GetValue(); + const auto setup = values.resolution_setup.GetValue(); auto& info = values.resolution_info; switch (setup) { case ResolutionSetup::Res1_2X: diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d94f1e89f..bb24a0656 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -554,7 +554,7 @@ void RasterizerOpenGL::SyncViewport() { } glFrontFace(mode); } - if (dirty_viewport || flags[Dirty::ClipControl]) { + if (dirty_viewport || dirty_clip_control) { flags[Dirty::ClipControl] = false; bool flip_y = false; @@ -925,7 +925,7 @@ void RasterizerOpenGL::SyncScissorTest() { const auto& regs = maxwell3d.regs; const auto& resolution = Settings::values.resolution_info; - const auto scale_up = [&](u32 value) -> u32 { + const auto scale_up = [resolution](u32 value) -> u32 { if (value == 0) { return 0U; } diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index fafee62ee..c68a51ebb 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -405,7 +405,8 @@ ImageBufferMap::~ImageBufferMap() { TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& program_manager, StateTracker& state_tracker_) - : device{device_}, state_tracker{state_tracker_}, util_shaders(program_manager) { + : device{device_}, state_tracker{state_tracker_}, + util_shaders(program_manager), resolution{Settings::values.resolution_info} { static constexpr std::array TARGETS{GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D}; for (size_t i = 0; i < TARGETS.size(); ++i) { const GLenum target = TARGETS[i]; @@ -473,7 +474,6 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& set_view(Shader::TextureType::ColorArray2D, null_image_view_2d_array.handle); set_view(Shader::TextureType::ColorArrayCube, null_image_cube_array.handle); - resolution = Settings::values.resolution_info; if (resolution.active) { for (size_t i = 0; i < rescale_draw_fbos.size(); ++i) { rescale_draw_fbos[i].Create(); @@ -681,7 +681,7 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, gl_type = tuple.type; } texture = MakeImage(info, gl_internal_format); - original_backup = texture.handle; + current_texture = texture.handle; if (runtime->device.HasDebuggingToolAttached()) { const std::string name = VideoCommon::Name(*this); glObjectLabel(ImageTarget(info) == GL_TEXTURE_BUFFER ? GL_BUFFER : GL_TEXTURE, @@ -726,10 +726,6 @@ void Image::UploadMemory(const ImageBufferMap& map, void Image::DownloadMemory(ImageBufferMap& map, std::span copies) { glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); // TODO: Move this to its own API - const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); - if (is_rescaled) { - ScaleDown(); - } glBindBuffer(GL_PIXEL_PACK_BUFFER, map.buffer); glPixelStorei(GL_PACK_ALIGNMENT, 1); @@ -747,9 +743,6 @@ void Image::DownloadMemory(ImageBufferMap& map, } CopyImageToBuffer(copy, map.offset); } - if (is_rescaled) { - texture.handle = upscaled_backup.handle; - } } GLuint Image::StorageHandle() noexcept { @@ -775,11 +768,11 @@ GLuint Image::StorageHandle() noexcept { return store_view.handle; } store_view.Create(); - glTextureView(store_view.handle, ImageTarget(info), texture.handle, GL_RGBA8, 0, + glTextureView(store_view.handle, ImageTarget(info), current_texture, GL_RGBA8, 0, info.resources.levels, 0, info.resources.layers); return store_view.handle; default: - return texture.handle; + return current_texture; } } @@ -940,10 +933,10 @@ bool Image::Scale() { const u32 original_width = info.size.width; const u32 original_height = info.size.height; - auto dst_info = info; - dst_info.size.width = scaled_width; - dst_info.size.height = scaled_height; if (!upscaled_backup.handle) { + auto dst_info = info; + dst_info.size.width = scaled_width; + dst_info.size.height = scaled_height; upscaled_backup = MakeImage(dst_info, gl_internal_format); } const GLuint read_fbo = runtime->rescale_read_fbos[fbo_index].handle; @@ -955,14 +948,14 @@ bool Image::Scale() { const u32 dst_level_width = std::max(1u, scaled_width >> level); const u32 dst_level_height = std::max(1u, scaled_height >> level); - glNamedFramebufferTextureLayer(read_fbo, attachment, original_backup, level, layer); + glNamedFramebufferTextureLayer(read_fbo, attachment, texture.handle, level, layer); glNamedFramebufferTextureLayer(draw_fbo, attachment, upscaled_backup.handle, level, layer); glBlitNamedFramebuffer(read_fbo, draw_fbo, 0, 0, src_level_width, src_level_height, 0, 0, dst_level_width, dst_level_height, mask, filter); } } - texture.handle = upscaled_backup.handle; + current_texture = upscaled_backup.handle; return true; } @@ -993,7 +986,7 @@ bool Image::ScaleDown() { return false; } flags &= ~ImageFlagBits::Rescaled; - texture.handle = original_backup; + current_texture = texture.handle; return true; } @@ -1010,7 +1003,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI flat_range = info.range; set_object_label = device.HasDebuggingToolAttached(); is_render_target = info.IsRenderTarget(); - original_texture = image.texture.handle; + original_texture = image.Handle(); num_samples = image.info.num_samples; if (!is_render_target) { swizzle[0] = info.x_source; diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 61f9b0259..cf7f37a16 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -9,13 +9,16 @@ #include -#include "common/settings.h" #include "shader_recompiler/shader_info.h" #include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/util_shaders.h" #include "video_core/texture_cache/image_view_base.h" #include "video_core/texture_cache/texture_cache_base.h" +namespace Settings { +struct ResolutionScalingInfo; +} + namespace OpenGL { class Device; @@ -155,7 +158,7 @@ private: std::array rescale_draw_fbos; std::array rescale_read_fbos; - Settings::ResolutionScalingInfo resolution; + const Settings::ResolutionScalingInfo& resolution; }; class Image : public VideoCommon::ImageBase { @@ -182,7 +185,7 @@ public: GLuint StorageHandle() noexcept; GLuint Handle() const noexcept { - return texture.handle; + return current_texture; } GLuint GlFormat() const noexcept { @@ -211,7 +214,7 @@ private: GLenum gl_format = GL_NONE; GLenum gl_type = GL_NONE; TextureCacheRuntime* runtime{}; - GLuint original_backup{}; + GLuint current_texture{}; }; class ImageView : public VideoCommon::ImageViewBase { diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index ac2bbebe0..40a149832 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h @@ -71,13 +71,15 @@ public: } bool TouchViewports() { - return Exchange(Dirty::Viewports, false) || - Exchange(VideoCommon::Dirty::RescaleViewports, false); + const bool dirty_viewports = Exchange(Dirty::Viewports, false); + const bool rescale_viewports = Exchange(VideoCommon::Dirty::RescaleViewports, false); + return dirty_viewports || rescale_viewports; } bool TouchScissors() { - return Exchange(Dirty::Scissors, false) || - Exchange(VideoCommon::Dirty::RescaleScissors, false); + const bool dirty_scissors = Exchange(Dirty::Scissors, false); + const bool rescale_scissors = Exchange(VideoCommon::Dirty::RescaleScissors, false); + return dirty_scissors || rescale_scissors; } bool TouchDepthBias() { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 4f0bab274..930c7d569 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -125,8 +125,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { } } -[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info, - u32 up, u32 down) { +[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) { const PixelFormat format = StorageFormat(info.format); const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format); VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; @@ -137,9 +136,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { if (info.type == ImageType::e3D) { flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; } - const auto scale_up = [&](u32 value) { return std::max((value * up) >> down, 1U); }; const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples); - const bool is_2d = info.type == ImageType::e2D; return VkImageCreateInfo{ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = nullptr, @@ -147,8 +144,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { .imageType = ConvertImageType(info.type), .format = format_info.format, .extent{ - .width = scale_up(info.size.width) >> samples_x, - .height = (is_2d ? scale_up(info.size.height) : info.size.height) >> samples_y, + .width = info.size.width >> samples_x, + .height = info.size.height >> samples_y, .depth = info.size.depth, }, .mipLevels = static_cast(info.resources.levels), @@ -163,12 +160,11 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { }; } -[[nodiscard]] vk::Image MakeImage(const Device& device, const ImageInfo& info, u32 up = 1, - u32 down = 0) { +[[nodiscard]] vk::Image MakeImage(const Device& device, const ImageInfo& info) { if (info.type == ImageType::Buffer) { return vk::Image{}; } - return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info, up, down)); + return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info)); } [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { @@ -860,10 +856,9 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, nullptr, nullptr, read_barriers); if (is_resolve) { - VkImageResolve resolve_info = - MakeImageResolve(dst_region, src_region, dst_layers, src_layers); cmdbuf.ResolveImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, resolve_info); + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + MakeImageResolve(dst_region, src_region, dst_layers, src_layers)); } else { const bool is_linear = filter == Fermi2D::Filter::Bilinear; const VkFilter vk_filter = is_linear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; @@ -1143,7 +1138,17 @@ bool Image::ScaleUp() { } const auto& device = runtime->device; if (!scaled_image) { - scaled_image = MakeImage(device, info, resolution.up_scale, resolution.down_shift); + const u32 up = resolution.up_scale; + const u32 down = resolution.down_shift; + const auto scale = [&](u32 value) { return std::max((value * up) >> down, 1U); }; + + const bool is_2d = info.type == ImageType::e2D; + const u32 scaled_width = scale(info.size.width); + const u32 scaled_height = is_2d ? scale(info.size.height) : info.size.height; + auto scaled_info = info; + scaled_info.size.width = scaled_width; + scaled_info.size.height = scaled_height; + scaled_image = MakeImage(device, scaled_info); auto& allocator = runtime->memory_allocator; scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal)); } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index e5060e3f1..5381343e9 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -6,7 +6,6 @@ #include -#include "common/settings.h" #include "shader_recompiler/shader_info.h" #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" #include "video_core/texture_cache/image_view_base.h" @@ -14,6 +13,10 @@ #include "video_core/vulkan_common/vulkan_memory_allocator.h" #include "video_core/vulkan_common/vulkan_wrapper.h" +namespace Settings { +struct ResolutionScalingInfo; +} + namespace Vulkan { using VideoCommon::ImageId; @@ -86,7 +89,7 @@ public: BlitImageHelper& blit_image_helper; ASTCDecoderPass& astc_decoder_pass; RenderPassCache& render_pass_cache; - Settings::ResolutionScalingInfo resolution; + const Settings::ResolutionScalingInfo& resolution; }; class Image : public VideoCommon::ImageBase { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index b708e41b5..630c73005 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1726,9 +1726,7 @@ void TextureCache

::CopyImage(ImageId dst_id, ImageId src_id, std::vector Date: Wed, 6 Oct 2021 02:02:05 -0400 Subject: vk_texture_cache: Fix early returns on unsupported scales --- .../renderer_vulkan/vk_texture_cache.cpp | 28 ++++++++-------------- src/video_core/texture_cache/texture_cache.h | 2 +- 2 files changed, 11 insertions(+), 19 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 930c7d569..1ab2b1fe9 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1130,13 +1130,19 @@ bool Image::ScaleUp() { return false; } ASSERT(info.type != ImageType::Linear); - flags |= ImageFlagBits::Rescaled; - const auto& resolution = runtime->resolution; if (!resolution.active) { - return true; + return false; } const auto& device = runtime->device; + const PixelFormat format = StorageFormat(info.format); + const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format); + const auto similar = device.GetSupportedFormat( + format_info.format, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT), + FormatType::Optimal); + if (similar != format_info.format) { + return true; + } if (!scaled_image) { const u32 up = resolution.up_scale; const u32 down = resolution.down_shift; @@ -1155,23 +1161,9 @@ bool Image::ScaleUp() { if (aspect_mask == 0) { aspect_mask = ImageAspectMask(info.format); } - if (info.num_samples > 1) { - return true; - } - const PixelFormat format = StorageFormat(info.format); - const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format); - const auto similar = device.GetSupportedFormat( - format_info.format, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT), - FormatType::Optimal); - - if (similar != format_info.format) { - return true; - } - if (aspect_mask == 0) { - aspect_mask = ImageAspectMask(info.format); - } BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution, true); current_image = *scaled_image; + flags |= ImageFlagBits::Rescaled; return true; } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 630c73005..de522cc43 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -857,7 +857,7 @@ u64 TextureCache

::GetScaledImageSizeBytes(Image& image) { const f32 add_to_size = Settings::values.resolution_info.up_factor - 1.0f; const bool sign = std::signbit(add_to_size); const u32 image_size_bytes = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); - const u64 tentative_size = static_cast(image_size_bytes * std::abs(add_to_size)); + const u64 tentative_size = image_size_bytes * static_cast(std::abs(add_to_size)); const u64 fitted_size = Common::AlignUp(tentative_size, 1024); return sign ? -fitted_size : fitted_size; } -- cgit v1.2.3 From b14f2c7c826b8bbea02c1f2674ab024a5ae0695e Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:55:53 -0400 Subject: texture_cache: Fix image resolves when src/dst are not both scaled --- src/video_core/texture_cache/texture_cache.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index de522cc43..38895c2e9 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -475,12 +475,10 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, Image& dst_image = slot_images[dst_id]; Image& src_image = slot_images[src_id]; - - bool is_resolve = src_image.info.num_samples != 1 && dst_image.info.num_samples == 1; - bool is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); bool is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); + const bool is_resolve = src_image.info.num_samples != 1 && dst_image.info.num_samples == 1; if (is_src_rescaled != is_dst_rescaled) { if (ImageCanRescale(src_image)) { ScaleUp(src_image); @@ -498,7 +496,13 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); } } - + if (is_resolve && (is_src_rescaled != is_dst_rescaled)) { + // A resolve requires both images to be the same dimensions. Resize down if needed. + ScaleDown(src_image); + ScaleDown(dst_image); + is_src_rescaled = True(src_image.flags & ImageFlagBits::Rescaled); + is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); + } const auto& resolution = Settings::values.resolution_info; const auto scale_up = [&](u32 value) -> u32 { if (value == 0) { @@ -506,7 +510,6 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, } return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); }; - const auto scale_region = [&](Region2D& region) { region.start.x = scale_up(region.start.x); region.start.y = scale_up(region.start.y); -- cgit v1.2.3 From abd07e41582b6d8f7efdedb936cdd7a7fddf9912 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 12 Oct 2021 00:35:01 -0400 Subject: video_core: Refactor resolution scale function --- src/common/settings.h | 14 ++++++++ .../renderer_opengl/gl_texture_cache.cpp | 8 ++--- .../renderer_vulkan/vk_texture_cache.cpp | 19 ++++------- src/video_core/texture_cache/texture_cache.h | 39 +++++++--------------- 4 files changed, 34 insertions(+), 46 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/common/settings.h b/src/common/settings.h index f629c7c56..09f7cdd84 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -72,6 +72,20 @@ struct ResolutionScalingInfo { f32 up_factor{1.0f}; f32 down_factor{1.0f}; bool active{}; + + s32 ScaleUp(s32 value) const { + if (value == 0) { + return 0; + } + return std::max((value * static_cast(up_scale)) >> static_cast(down_shift), 1); + } + + u32 ScaleUp(u32 value) const { + if (value == 0U) { + return 0U; + } + return std::max((value * up_scale) >> down_shift, 1U); + } }; /** The BasicSetting class is a simple resource manager. It defines a label and default value diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 3dfd13d6a..ec1afd31a 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -924,12 +924,8 @@ bool Image::Scale() { const GLenum filter = linear_color_format ? GL_LINEAR : GL_NEAREST; const auto& resolution = runtime->resolution; - const u32 up = resolution.up_scale; - const u32 down = resolution.down_shift; - const auto scale = [&](u32 value) { return std::max((value * up) >> down, 1U); }; - - const u32 scaled_width = scale(info.size.width); - const u32 scaled_height = is_2d ? scale(info.size.height) : info.size.height; + const u32 scaled_width = resolution.ScaleUp(info.size.width); + const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; const u32 original_width = info.size.width; const u32 original_height = info.size.height; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 65506f75e..caefce5fc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -607,16 +607,13 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([dst_image, src_image, extent, resources, aspect_mask, resolution, type, scaling, vk_filter](vk::CommandBuffer cmdbuf) { - const auto scale_up = [&](u32 value) { - return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); - }; const VkOffset2D src_size{ - .x = static_cast(scaling ? extent.width : scale_up(extent.width)), - .y = static_cast(scaling ? extent.height : scale_up(extent.height)), + .x = static_cast(scaling ? extent.width : resolution.ScaleUp(extent.width)), + .y = static_cast(scaling ? extent.height : resolution.ScaleUp(extent.height)), }; const VkOffset2D dst_size{ - .x = static_cast(scaling ? scale_up(extent.width) : extent.width), - .y = static_cast(scaling ? scale_up(extent.height) : extent.height), + .x = static_cast(scaling ? resolution.ScaleUp(extent.width) : extent.width), + .y = static_cast(scaling ? resolution.ScaleUp(extent.height) : extent.height), }; boost::container::small_vector regions; regions.reserve(resources.levels); @@ -1144,13 +1141,9 @@ bool Image::ScaleUp() { return false; } if (!scaled_image) { - const u32 up = resolution.up_scale; - const u32 down = resolution.down_shift; - const auto scale = [&](u32 value) { return std::max((value * up) >> down, 1U); }; - const bool is_2d = info.type == ImageType::e2D; - const u32 scaled_width = scale(info.size.width); - const u32 scaled_height = is_2d ? scale(info.size.height) : info.size.height; + const u32 scaled_width = resolution.ScaleUp(info.size.width); + const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; auto scaled_info = info; scaled_info.size.width = scaled_width; scaled_info.size.height = scaled_height; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 38895c2e9..c77332b46 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -504,17 +504,11 @@ void TextureCache

::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, is_dst_rescaled = True(dst_image.flags & ImageFlagBits::Rescaled); } const auto& resolution = Settings::values.resolution_info; - const auto scale_up = [&](u32 value) -> u32 { - if (value == 0) { - return 0U; - } - return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); - }; const auto scale_region = [&](Region2D& region) { - region.start.x = scale_up(region.start.x); - region.start.y = scale_up(region.start.y); - region.end.x = scale_up(region.end.x); - region.end.y = scale_up(region.end.y); + region.start.x = resolution.ScaleUp(region.start.x); + region.start.y = resolution.ScaleUp(region.start.y); + region.end.x = resolution.ScaleUp(region.end.x); + region.end.y = resolution.ScaleUp(region.end.y); }; // TODO: Deduplicate @@ -1721,20 +1715,14 @@ void TextureCache

::CopyImage(ImageId dst_id, ImageId src_id, std::vector u32 { - if (value == 0) { - return 0U; - } - return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); - }; for (auto& copy : copies) { - copy.src_offset.x = scale_up(copy.src_offset.x); - copy.dst_offset.x = scale_up(copy.dst_offset.x); - copy.extent.width = scale_up(copy.extent.width); + copy.src_offset.x = resolution.ScaleUp(copy.src_offset.x); + copy.dst_offset.x = resolution.ScaleUp(copy.dst_offset.x); + copy.extent.width = resolution.ScaleUp(copy.extent.width); if (both_2d) { - copy.src_offset.y = scale_up(copy.src_offset.y); - copy.dst_offset.y = scale_up(copy.dst_offset.y); - copy.extent.height = scale_up(copy.extent.height); + copy.src_offset.y = resolution.ScaleUp(copy.src_offset.y); + copy.dst_offset.y = resolution.ScaleUp(copy.dst_offset.y); + copy.extent.height = resolution.ScaleUp(copy.extent.height); } } } @@ -1812,12 +1800,9 @@ std::pair TextureCache

::RenderTargetFromImage( Extent3D extent = MipSize(image.info.size, view_info.range.base.level); if (is_rescaled) { const auto& resolution = Settings::values.resolution_info; - const auto scale_up = [&](u32 value) { - return std::max((value * resolution.up_scale) >> resolution.down_shift, 1U); - }; - extent.width = scale_up(extent.width); + extent.width = resolution.ScaleUp(extent.width); if (image.info.type == ImageType::e2D) { - extent.height = scale_up(extent.height); + extent.height = resolution.ScaleUp(extent.height); } } const u32 num_samples = image.info.num_samples; -- cgit v1.2.3 From 4de584005fe8ae00608f8c3267a78e7cf0eb52aa Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 12 Oct 2021 01:45:54 -0400 Subject: texture_cache: Fix infinitely recursive ImageCanRescale check --- src/video_core/texture_cache/image_base.cpp | 2 ++ src/video_core/texture_cache/image_base.h | 5 +++-- src/video_core/texture_cache/texture_cache.h | 16 ++++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/image_base.cpp b/src/video_core/texture_cache/image_base.cpp index 25a211df8..1909c9ecb 100644 --- a/src/video_core/texture_cache/image_base.cpp +++ b/src/video_core/texture_cache/image_base.cpp @@ -256,6 +256,8 @@ void AddImageAlias(ImageBase& lhs, ImageBase& rhs, ImageId lhs_id, ImageId rhs_i } lhs.aliased_images.push_back(std::move(lhs_alias)); rhs.aliased_images.push_back(std::move(rhs_alias)); + lhs.flags &= ~ImageFlagBits::IsRescalable; + rhs.flags &= ~ImageFlagBits::IsRescalable; } } // namespace VideoCommon diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 9c34687e0..bab290ac7 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -36,8 +36,9 @@ enum class ImageFlagBits : u32 { // Rescaler Rescaled = 1 << 12, - RescaleChecked = 1 << 13, - Blacklisted = 1 << 14, + CheckingRescalable = 1 << 13, + IsRescalable = 1 << 14, + Blacklisted = 1 << 15, }; DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index c77332b46..c1fb12679 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -795,25 +795,25 @@ bool TextureCache

::BlackListImage(ImageId image_id) { template bool TextureCache

::ImageCanRescale(ImageBase& image) { - if (True(image.flags & ImageFlagBits::Blacklisted)) { + if (!image.info.rescaleable || True(image.flags & ImageFlagBits::Blacklisted)) { return false; } - if (True(image.flags & (ImageFlagBits::Rescaled | ImageFlagBits::RescaleChecked))) { + if (True(image.flags & (ImageFlagBits::Rescaled | ImageFlagBits::CheckingRescalable))) { return true; } - if (!image.info.rescaleable) { - image.flags &= ~ImageFlagBits::RescaleChecked; - return false; + if (True(image.flags & ImageFlagBits::IsRescalable)) { + return true; } - image.flags |= ImageFlagBits::RescaleChecked; + image.flags |= ImageFlagBits::CheckingRescalable; for (const auto& alias : image.aliased_images) { Image& other_image = slot_images[alias.id]; if (!ImageCanRescale(other_image)) { - image.flags &= ~ImageFlagBits::RescaleChecked; + image.flags &= ~ImageFlagBits::CheckingRescalable; return false; } } - image.flags &= ~ImageFlagBits::RescaleChecked; + image.flags &= ~ImageFlagBits::CheckingRescalable; + image.flags |= ImageFlagBits::IsRescalable; return true; } -- cgit v1.2.3 From 0f14c9379eae9c3caf8f4b932eace0a84d728f94 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Thu, 14 Oct 2021 14:12:25 -0400 Subject: texture_cache_base: Remove unused function declarations --- src/video_core/texture_cache/texture_cache_base.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 40e003b60..4dbe050af 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -144,14 +144,6 @@ public: const Tegra::Engines::Fermi2D::Surface& src, const Tegra::Engines::Fermi2D::Config& copy); - /// Invalidate the contents of the color buffer index - /// These contents become unspecified, the cache can assume aggressive optimizations. - void InvalidateColorBuffer(size_t index); - - /// Invalidate the contents of the depth buffer - /// These contents become unspecified, the cache can assume aggressive optimizations. - void InvalidateDepthBuffer(); - /// Try to find a cached image view in the given CPU address [[nodiscard]] ImageView* TryFindFramebufferImageView(VAddr cpu_addr); -- cgit v1.2.3 From b7ccc58f235d9e442677eb10259b7196a387c6bc Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 15 Oct 2021 22:59:16 +0200 Subject: Texture Cahe: Fix downscaling on SMO. --- src/common/settings.cpp | 2 ++ src/common/settings.h | 1 + src/video_core/texture_cache/image_info.cpp | 4 ++++ src/video_core/texture_cache/image_info.h | 1 + src/video_core/texture_cache/texture_cache.h | 3 +++ 5 files changed, 11 insertions(+) (limited to 'src/video_core/texture_cache') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 12fdb0f9b..bc2c8c7d7 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -109,10 +109,12 @@ float Volume() { void UpdateRescalingInfo() { const auto setup = values.resolution_setup.GetValue(); auto& info = values.resolution_info; + info.downscale = false; switch (setup) { case ResolutionSetup::Res1_2X: info.up_scale = 1; info.down_shift = 1; + info.downscale = true; break; case ResolutionSetup::Res1X: info.up_scale = 1; diff --git a/src/common/settings.h b/src/common/settings.h index 09f7cdd84..a09db0822 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -72,6 +72,7 @@ struct ResolutionScalingInfo { f32 up_factor{1.0f}; f32 down_factor{1.0f}; bool active{}; + bool downscale{}; s32 ScaleUp(s32 value) const { if (value == 0) { diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 7fa8fd4fe..d8e414247 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -102,6 +102,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { layer_stride = CalculateLayerStride(*this); maybe_unaligned_layer_stride = CalculateLayerSize(*this); rescaleable &= (block.depth == 0) && resources.levels == 1; + downscaleable = size.height > 512; } } @@ -135,6 +136,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) size.depth = rt.depth; } else { rescaleable = block.depth == 0 && size.height > 256; + downscaleable = size.height > 512; type = ImageType::e2D; resources.layers = rt.depth; } @@ -164,6 +166,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept { size.depth = regs.zeta_depth; } else { rescaleable = block.depth == 0 && size.height > 256; + downscaleable = size.height > 512; type = ImageType::e2D; resources.layers = regs.zeta_depth; } @@ -197,6 +200,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { .depth = 1, }; rescaleable = block.depth == 0 && size.height > 256; + downscaleable = size.height > 512; } } diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index e874d2870..5932dcaba 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -34,6 +34,7 @@ struct ImageInfo { u32 num_samples = 1; u32 tile_width_spacing = 0; bool rescaleable = false; + bool downscaleable = false; }; } // namespace VideoCommon diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index c1fb12679..261cb6c48 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -798,6 +798,9 @@ bool TextureCache

::ImageCanRescale(ImageBase& image) { if (!image.info.rescaleable || True(image.flags & ImageFlagBits::Blacklisted)) { return false; } + if (Settings::values.resolution_info.downscale && !image.info.downscaleable) { + return false; + } if (True(image.flags & (ImageFlagBits::Rescaled | ImageFlagBits::CheckingRescalable))) { return true; } -- cgit v1.2.3 From ef1dc4263586f5b81b53a5158db2c1cd2086ed4c Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 17 Oct 2021 01:22:13 +0200 Subject: Texture cache: Fix memory consumption and ignore rating when a depth texture is rendered. --- src/video_core/renderer_opengl/gl_texture_cache.cpp | 10 ++++++++-- src/video_core/renderer_vulkan/vk_texture_cache.cpp | 9 +++++++-- src/video_core/texture_cache/texture_cache.h | 7 ++++--- 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index ec1afd31a..944a3aa65 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -967,21 +967,24 @@ bool Image::ScaleUp() { if (True(flags & ImageFlagBits::Rescaled)) { return false; } + flags |= ImageFlagBits::Rescaled; if (!runtime->resolution.active) { return false; } if (gl_format == 0 && gl_type == 0) { // compressed textures + flags &= ~ImageFlagBits::Rescaled; return false; } if (info.type == ImageType::Linear) { - UNIMPLEMENTED(); + UNREACHABLE(); + flags &= ~ImageFlagBits::Rescaled; return false; } if (!Scale()) { + flags &= ~ImageFlagBits::Rescaled; return false; } - flags |= ImageFlagBits::Rescaled; return true; } @@ -990,6 +993,9 @@ bool Image::ScaleDown() { return false; } flags &= ~ImageFlagBits::Rescaled; + if (!runtime->resolution.active) { + return false; + } current_texture = texture.handle; return true; } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 9b90c7d9b..a4fbbc735 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1126,6 +1126,7 @@ bool Image::ScaleUp() { return false; } ASSERT(info.type != ImageType::Linear); + flags |= ImageFlagBits::Rescaled; const auto& resolution = runtime->resolution; if (!resolution.active) { return false; @@ -1188,11 +1189,11 @@ bool Image::ScaleUp() { dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); } else { // TODO: Use helper blits where applicable + flags &= ~ImageFlagBits::Rescaled; LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", format); return false; } } - flags |= ImageFlagBits::Rescaled; return true; } @@ -1200,8 +1201,12 @@ bool Image::ScaleDown() { if (False(flags & ImageFlagBits::Rescaled)) { return false; } - ASSERT(info.type != ImageType::Linear); flags &= ~ImageFlagBits::Rescaled; + const auto& resolution = runtime->resolution; + if (!resolution.active) { + return false; + } + ASSERT(info.type != ImageType::Linear); current_image = *original_image; return true; } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 261cb6c48..c06cddae9 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -230,7 +230,8 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { auto& image = slot_images[image_id]; can_rescale &= ImageCanRescale(image); any_blacklisted |= True(image.flags & ImageFlagBits::Blacklisted); - any_rescaled |= True(image.flags & ImageFlagBits::Rescaled); + any_rescaled |= True(image.flags & ImageFlagBits::Rescaled) || + GetFormatType(image.info.format) != SurfaceType::ColorTexture; scale_rating = std::max(scale_rating, image.scale_tick <= frame_tick ? image.scale_rating + 1U : image.scale_rating); @@ -857,7 +858,7 @@ u64 TextureCache

::GetScaledImageSizeBytes(Image& image) { const f32 add_to_size = Settings::values.resolution_info.up_factor - 1.0f; const bool sign = std::signbit(add_to_size); const u32 image_size_bytes = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); - const u64 tentative_size = image_size_bytes * static_cast(std::abs(add_to_size)); + const u64 tentative_size = image_size_bytes * static_cast(std::abs(add_to_size)); const u64 fitted_size = Common::AlignUp(tentative_size, 1024); return sign ? -fitted_size : fitted_size; } @@ -879,7 +880,7 @@ bool TextureCache

::ScaleDown(Image& image) { if (!rescaled) { return false; } - total_used_memory += GetScaledImageSizeBytes(image); + total_used_memory -= GetScaledImageSizeBytes(image); InvalidateScale(image); return true; } -- cgit v1.2.3 From d4f5193bd308988a80f52941d9eefc4c857bfa99 Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Sun, 17 Oct 2021 02:21:26 +0200 Subject: Texture Cache: Rescale conversions between depth and color --- src/video_core/renderer_opengl/gl_texture_cache.h | 2 +- src/video_core/renderer_vulkan/blit_image.cpp | 29 +++++++++++++--------- src/video_core/renderer_vulkan/blit_image.h | 14 +++++++---- .../renderer_vulkan/vk_texture_cache.cpp | 13 ++++++---- src/video_core/renderer_vulkan/vk_texture_cache.h | 2 +- src/video_core/texture_cache/texture_cache.h | 2 +- 6 files changed, 37 insertions(+), 25 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index cf7f37a16..f90dbfe9e 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -84,7 +84,7 @@ public: void CopyImage(Image& dst, Image& src, std::span copies); - void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) { + void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { UNIMPLEMENTED(); } diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index b97aac550..bc3e4b93d 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -418,40 +418,45 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, } void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, - const ImageView& src_image_view) { + const ImageView& src_image_view, u32 up_scale, + u32 down_shift) { ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass()); - Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); } void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, - const ImageView& src_image_view) { + const ImageView& src_image_view, u32 up_scale, + u32 down_shift) { ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); - Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); } void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer, - const ImageView& src_image_view) { + const ImageView& src_image_view, u32 up_scale, + u32 down_shift) { ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass()); - Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); } void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, - const ImageView& src_image_view) { + const ImageView& src_image_view, u32 up_scale, + u32 down_shift) { ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass()); - Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view); + Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); } void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, - const ImageView& src_image_view) { + const ImageView& src_image_view, u32 up_scale, u32 down_shift) { const VkPipelineLayout layout = *one_texture_pipeline_layout; const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); const VkSampler sampler = *nearest_sampler; const VkExtent2D extent{ - .width = src_image_view.size.width, - .height = src_image_view.size.height, + .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), + .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U), }; scheduler.RequestRenderpass(dst_framebuffer); - scheduler.Record([pipeline, layout, sampler, src_view, extent, this](vk::CommandBuffer cmdbuf) { + scheduler.Record([pipeline, layout, sampler, src_view, extent, up_scale, down_shift, + this](vk::CommandBuffer cmdbuf) { const VkOffset2D offset{ .x = 0, .y = 0, diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index e11f8c214..c0f4a16a4 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h @@ -44,17 +44,21 @@ public: const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, Tegra::Engines::Fermi2D::Operation operation); - void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); + void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, + u32 up_scale, u32 down_shift); - void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); + void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, + u32 up_scale, u32 down_shift); - void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); + void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, + u32 up_scale, u32 down_shift); - void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); + void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, + u32 up_scale, u32 down_shift); private: void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, - const ImageView& src_image_view); + const ImageView& src_image_view, u32 up_scale, u32 down_shift); [[nodiscard]] VkPipeline FindOrEmplacePipeline(const BlitImagePipelineKey& key); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index a4fbbc735..17c62e27d 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -867,26 +867,29 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst }); } -void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) { +void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, + bool rescaled) { + const u32 up_scale = rescaled ? resolution.up_scale : 1; + const u32 down_shift = rescaled ? resolution.down_shift : 0; switch (dst_view.format) { case PixelFormat::R16_UNORM: if (src_view.format == PixelFormat::D16_UNORM) { - return blit_image_helper.ConvertD16ToR16(dst, src_view); + return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); } break; case PixelFormat::R32_FLOAT: if (src_view.format == PixelFormat::D32_FLOAT) { - return blit_image_helper.ConvertD32ToR32(dst, src_view); + return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); } break; case PixelFormat::D16_UNORM: if (src_view.format == PixelFormat::R16_UNORM) { - return blit_image_helper.ConvertR16ToD16(dst, src_view); + return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); } break; case PixelFormat::D32_FLOAT: if (src_view.format == PixelFormat::R32_FLOAT) { - return blit_image_helper.ConvertR32ToD32(dst, src_view); + return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); } break; default: diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index dc9175ee1..6dc190632 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -61,7 +61,7 @@ public: void CopyImage(Image& dst, Image& src, std::span copies); - void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view); + void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); bool CanAccelerateImageUpload(Image&) const noexcept { return false; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index c06cddae9..a035d2b18 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1774,7 +1774,7 @@ void TextureCache

::CopyImage(ImageId dst_id, ImageId src_id, std::vector Date: Sun, 17 Oct 2021 18:01:18 +0200 Subject: Texture Cache: Fix downscaling and correct memory comsumption. --- .../renderer_opengl/gl_texture_cache.cpp | 43 +++++++--- src/video_core/renderer_opengl/gl_texture_cache.h | 2 +- .../renderer_vulkan/vk_texture_cache.cpp | 93 +++++++++++++++++++--- src/video_core/renderer_vulkan/vk_texture_cache.h | 3 + src/video_core/texture_cache/image_base.cpp | 4 +- src/video_core/texture_cache/image_base.h | 5 ++ src/video_core/texture_cache/texture_cache.h | 31 +++++--- src/video_core/texture_cache/texture_cache_base.h | 2 +- 8 files changed, 147 insertions(+), 36 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 944a3aa65..34d3723e5 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -876,7 +876,7 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b } } -bool Image::Scale() { +bool Image::Scale(bool up_scale) { const auto format_type = GetFormatType(info.format); const GLenum attachment = [format_type] { switch (format_type) { @@ -944,14 +944,25 @@ bool Image::Scale() { const GLuint draw_fbo = runtime->rescale_draw_fbos[fbo_index].handle; for (s32 layer = 0; layer < info.resources.layers; ++layer) { for (s32 level = 0; level < info.resources.levels; ++level) { - const u32 src_level_width = std::max(1u, original_width >> level); - const u32 src_level_height = std::max(1u, original_height >> level); - const u32 dst_level_width = std::max(1u, scaled_width >> level); - const u32 dst_level_height = std::max(1u, scaled_height >> level); - - glNamedFramebufferTextureLayer(read_fbo, attachment, texture.handle, level, layer); - glNamedFramebufferTextureLayer(draw_fbo, attachment, upscaled_backup.handle, level, - layer); + const u32 src_level_width = + std::max(1u, (up_scale ? original_width : scaled_width) >> level); + const u32 src_level_height = + std::max(1u, (up_scale ? original_height : scaled_height) >> level); + const u32 dst_level_width = + std::max(1u, (up_scale ? scaled_width : original_width) >> level); + const u32 dst_level_height = + std::max(1u, (up_scale ? scaled_height : original_height) >> level); + + if (up_scale) { + glNamedFramebufferTextureLayer(read_fbo, attachment, texture.handle, level, layer); + glNamedFramebufferTextureLayer(draw_fbo, attachment, upscaled_backup.handle, level, + layer); + } else { + glNamedFramebufferTextureLayer(read_fbo, attachment, upscaled_backup.handle, level, + layer); + glNamedFramebufferTextureLayer(draw_fbo, attachment, texture.handle, level, layer); + } + glBlitNamedFramebuffer(read_fbo, draw_fbo, 0, 0, src_level_width, src_level_height, 0, 0, dst_level_width, dst_level_height, mask, filter); } @@ -959,7 +970,12 @@ bool Image::Scale() { if (scissor_test != GL_FALSE) { glEnablei(GL_SCISSOR_TEST, 0); } - current_texture = upscaled_backup.handle; + if (up_scale) { + current_texture = upscaled_backup.handle; + } else { + current_texture = texture.handle; + } + return true; } @@ -981,6 +997,7 @@ bool Image::ScaleUp() { flags &= ~ImageFlagBits::Rescaled; return false; } + scale_count++; if (!Scale()) { flags &= ~ImageFlagBits::Rescaled; return false; @@ -996,7 +1013,11 @@ bool Image::ScaleDown() { if (!runtime->resolution.active) { return false; } - current_texture = texture.handle; + scale_count++; + if (!Scale(false)) { + flags &= ~ImageFlagBits::Rescaled; + return false; + } return true; } diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index f90dbfe9e..81aaef3da 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -205,7 +205,7 @@ private: void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset); - bool Scale(); + bool Scale(bool up_scale = true); OGLTexture texture; OGLTexture upscaled_backup; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 17c62e27d..51367c01d 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -592,7 +592,8 @@ struct RangedBarrierRange { } void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info, - VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution) { + VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution, + bool up_scaling = true) { const bool is_2d = info.type == ImageType::e2D; const auto resources = info.resources; const VkExtent2D extent{ @@ -605,14 +606,16 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([dst_image, src_image, extent, resources, aspect_mask, resolution, is_2d, - vk_filter](vk::CommandBuffer cmdbuf) { + vk_filter, up_scaling](vk::CommandBuffer cmdbuf) { const VkOffset2D src_size{ - .x = static_cast(extent.width), - .y = static_cast(extent.height), + .x = static_cast(up_scaling ? extent.width : resolution.ScaleUp(extent.width)), + .y = static_cast(is_2d && up_scaling ? extent.height + : resolution.ScaleUp(extent.height)), }; const VkOffset2D dst_size{ - .x = static_cast(resolution.ScaleUp(extent.width)), - .y = static_cast(is_2d ? resolution.ScaleUp(extent.height) : extent.height), + .x = static_cast(up_scaling ? resolution.ScaleUp(extent.width) : extent.width), + .y = static_cast(is_2d && up_scaling ? resolution.ScaleUp(extent.height) + : extent.height), }; boost::container::small_vector regions; regions.reserve(resources.levels); @@ -1134,6 +1137,7 @@ bool Image::ScaleUp() { if (!resolution.active) { return false; } + scale_count++; const auto& device = runtime->device; const bool is_2d = info.type == ImageType::e2D; const u32 scaled_width = resolution.ScaleUp(info.size.width); @@ -1161,8 +1165,10 @@ bool Image::ScaleUp() { using namespace VideoCommon; static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; - const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); - scale_view = std::make_unique(*runtime, view_info, NULL_IMAGE_ID, *this); + if (!scale_view) { + const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); + scale_view = std::make_unique(*runtime, view_info, NULL_IMAGE_ID, *this); + } auto* view_ptr = scale_view.get(); const Region2D src_region{ @@ -1178,7 +1184,10 @@ bool Image::ScaleUp() { .height = scaled_height, }; if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { - scale_framebuffer = std::make_unique(*runtime, view_ptr, nullptr, extent); + if (!scale_framebuffer) { + scale_framebuffer = + std::make_unique(*runtime, view_ptr, nullptr, extent); + } const auto color_view = scale_view->Handle(Shader::TextureType::Color2D); runtime->blit_image_helper.BlitColor( @@ -1186,7 +1195,10 @@ bool Image::ScaleUp() { Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION); } else if (!runtime->device.IsBlitDepthStencilSupported() && aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { - scale_framebuffer = std::make_unique(*runtime, nullptr, view_ptr, extent); + if (!scale_framebuffer) { + scale_framebuffer = + std::make_unique(*runtime, view_ptr, nullptr, extent); + } runtime->blit_image_helper.BlitDepthStencil( scale_framebuffer.get(), scale_view->DepthView(), scale_view->StencilView(), dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); @@ -1209,6 +1221,67 @@ bool Image::ScaleDown() { if (!resolution.active) { return false; } + const auto& device = runtime->device; + const bool is_2d = info.type == ImageType::e2D; + const u32 scaled_width = resolution.ScaleUp(info.size.width); + const u32 scaled_height = is_2d ? resolution.ScaleUp(info.size.height) : info.size.height; + if (aspect_mask == 0) { + aspect_mask = ImageAspectMask(info.format); + } + static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal; + const PixelFormat format = StorageFormat(info.format); + const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format; + const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; + if (device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT)) { + BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false); + } else { + using namespace VideoCommon; + static constexpr auto BLIT_OPERATION = Tegra::Engines::Fermi2D::Operation::SrcCopy; + + if (!normal_view) { + const auto view_info = ImageViewInfo(ImageViewType::e2D, info.format); + normal_view = std::make_unique(*runtime, view_info, NULL_IMAGE_ID, *this); + } + auto* view_ptr = normal_view.get(); + + const Region2D src_region{ + .start = {0, 0}, + .end = {static_cast(scaled_width), static_cast(scaled_height)}, + }; + const Region2D dst_region{ + .start = {0, 0}, + .end = {static_cast(info.size.width), static_cast(info.size.height)}, + }; + const VkExtent2D extent{ + .width = scaled_width, + .height = scaled_height, + }; + if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { + if (!normal_framebuffer) { + normal_framebuffer = + std::make_unique(*runtime, view_ptr, nullptr, extent); + } + const auto color_view = normal_view->Handle(Shader::TextureType::Color2D); + + runtime->blit_image_helper.BlitColor( + normal_framebuffer.get(), color_view, dst_region, src_region, + Tegra::Engines::Fermi2D::Filter::Bilinear, BLIT_OPERATION); + } else if (!runtime->device.IsBlitDepthStencilSupported() && + aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + if (!normal_framebuffer) { + normal_framebuffer = + std::make_unique(*runtime, view_ptr, nullptr, extent); + } + runtime->blit_image_helper.BlitDepthStencil( + normal_framebuffer.get(), normal_view->DepthView(), normal_view->StencilView(), + dst_region, src_region, Tegra::Engines::Fermi2D::Filter::Point, BLIT_OPERATION); + } else { + // TODO: Use helper blits where applicable + flags &= ~ImageFlagBits::Rescaled; + LOG_ERROR(Render_Vulkan, "Device does not support scaling format {}", format); + return false; + } + } ASSERT(info.type != ImageType::Linear); current_image = *original_image; return true; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 6dc190632..df854a20c 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -148,6 +148,9 @@ private: std::unique_ptr scale_framebuffer; std::unique_ptr scale_view; + + std::unique_ptr normal_framebuffer; + std::unique_ptr normal_view; }; class ImageView : public VideoCommon::ImageViewBase { diff --git a/src/video_core/texture_cache/image_base.cpp b/src/video_core/texture_cache/image_base.cpp index 1909c9ecb..3db2ec825 100644 --- a/src/video_core/texture_cache/image_base.cpp +++ b/src/video_core/texture_cache/image_base.cpp @@ -60,8 +60,8 @@ namespace { ImageBase::ImageBase(const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_) : info{info_}, guest_size_bytes{CalculateGuestSizeInBytes(info)}, unswizzled_size_bytes{CalculateUnswizzledSizeBytes(info)}, - converted_size_bytes{CalculateConvertedSizeBytes(info)}, scale_rating{}, - scale_tick{}, gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, + converted_size_bytes{CalculateConvertedSizeBytes(info)}, scale_rating{}, scale_tick{}, + scale_count{}, gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, cpu_addr_end{cpu_addr + guest_size_bytes}, mip_level_offsets{CalculateMipLevelOffsets(info)} { if (info.type == ImageType::e3D) { slice_offsets = CalculateSliceOffsets(info); diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index bab290ac7..cd4b5f636 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -77,6 +77,10 @@ struct ImageBase { void CheckBadOverlapState(); void CheckAliasState(); + bool HasScaled() { + return scale_count > 0; + } + ImageInfo info; u32 guest_size_bytes = 0; @@ -84,6 +88,7 @@ struct ImageBase { u32 converted_size_bytes = 0; u32 scale_rating = 0; u64 scale_tick = 0; + u32 scale_count = 0; ImageFlagBits flags = ImageFlagBits::CpuModified; GPUVAddr gpu_addr = 0; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index a035d2b18..cf0d33a45 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -854,8 +854,8 @@ void TextureCache

::InvalidateScale(Image& image) { } template -u64 TextureCache

::GetScaledImageSizeBytes(Image& image) { - const f32 add_to_size = Settings::values.resolution_info.up_factor - 1.0f; +u64 TextureCache

::GetScaledImageSizeBytes(ImageBase& image) { + const f32 add_to_size = Settings::values.resolution_info.up_factor; const bool sign = std::signbit(add_to_size); const u32 image_size_bytes = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); const u64 tentative_size = image_size_bytes * static_cast(std::abs(add_to_size)); @@ -865,11 +865,14 @@ u64 TextureCache

::GetScaledImageSizeBytes(Image& image) { template bool TextureCache

::ScaleUp(Image& image) { + const bool has_copy = image.HasScaled(); const bool rescaled = image.ScaleUp(); if (!rescaled) { return false; } - total_used_memory += GetScaledImageSizeBytes(image); + if (!has_copy) { + total_used_memory += GetScaledImageSizeBytes(image); + } InvalidateScale(image); return true; } @@ -880,7 +883,10 @@ bool TextureCache

::ScaleDown(Image& image) { if (!rescaled) { return false; } - total_used_memory -= GetScaledImageSizeBytes(image); + const bool has_copy = image.HasScaled(); + if (!has_copy) { + total_used_memory -= GetScaledImageSizeBytes(image); + } InvalidateScale(image); return true; } @@ -1391,13 +1397,6 @@ void TextureCache

::UnregisterImage(ImageId image_id) { "Trying to unregister an already registered image"); image.flags &= ~ImageFlagBits::Registered; image.flags &= ~ImageFlagBits::BadOverlap; - u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); - if ((IsPixelFormatASTC(image.info.format) && - True(image.flags & ImageFlagBits::AcceleratedUpload)) || - True(image.flags & ImageFlagBits::Converted)) { - tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); - } - total_used_memory -= Common::AlignUp(tentative_size, 1024); lru_cache.Free(image.lru_index); const auto& clear_page_table = [this, image_id]( @@ -1478,6 +1477,16 @@ template void TextureCache

::TrackImage(ImageBase& image, ImageId image_id) { ASSERT(False(image.flags & ImageFlagBits::Tracked)); image.flags |= ImageFlagBits::Tracked; + if (image.HasScaled()) { + total_used_memory -= GetScaledImageSizeBytes(image); + } + u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); + if ((IsPixelFormatASTC(image.info.format) && + True(image.flags & ImageFlagBits::AcceleratedUpload)) || + True(image.flags & ImageFlagBits::Converted)) { + tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); + } + total_used_memory -= Common::AlignUp(tentative_size, 1024); if (False(image.flags & ImageFlagBits::Sparse)) { rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); return; diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 4dbe050af..e210393ba 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -331,7 +331,7 @@ private: void InvalidateScale(Image& image); bool ScaleUp(Image& image); bool ScaleDown(Image& image); - u64 GetScaledImageSizeBytes(Image& image); + u64 GetScaledImageSizeBytes(ImageBase& image); Runtime& runtime; VideoCore::RasterizerInterface& rasterizer; -- cgit v1.2.3 From c2ca55c9d576940cfb37ba8569b1656b72c65569 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 18 Oct 2021 14:04:54 +0200 Subject: Texture Cache: ease the requirements of textures being blacklisted. --- src/video_core/texture_cache/texture_cache.h | 27 ++++++----------------- src/video_core/texture_cache/texture_cache_base.h | 2 -- 2 files changed, 7 insertions(+), 22 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index cf0d33a45..c885586e8 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -221,7 +221,6 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { scale_rating = 0; bool any_rescaled = false; bool can_rescale = true; - bool any_blacklisted = false; const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { if (view_id != NULL_IMAGE_VIEW_ID && view_id != ImageViewId{}) { const auto& view = slot_image_views[view_id]; @@ -229,7 +228,6 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { id_save = image_id; auto& image = slot_images[image_id]; can_rescale &= ImageCanRescale(image); - any_blacklisted |= True(image.flags & ImageFlagBits::Blacklisted); any_rescaled |= True(image.flags & ImageFlagBits::Rescaled) || GetFormatType(image.info.format) != SurfaceType::ColorTexture; scale_rating = std::max(scale_rating, image.scale_tick <= frame_tick @@ -270,20 +268,17 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { } } else { rescaled = false; - const auto scale_down = [this, any_blacklisted](ImageId image_id) { + const auto scale_down = [this](ImageId image_id) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; ScaleDown(image); - if (any_blacklisted) { - image.flags |= ImageFlagBits::Blacklisted; - } } }; for (size_t index = 0; index < NUM_RT; ++index) { scale_down(tmp_color_images[index]); } scale_down(tmp_depth_image); - scale_rating = 0; + scale_rating = 1; } } while (has_deleted_images); // Rescale End @@ -352,7 +347,10 @@ void TextureCache

::FillImageViews(DescriptorTable& table, if constexpr (has_blacklists) { if (view.blacklist && view.id != NULL_IMAGE_VIEW_ID) { const ImageViewBase& image_view{slot_image_views[view.id]}; - has_blacklisted |= BlackListImage(image_view.image_id); + auto& image = slot_images[image_view.image_id]; + image.flags |= ImageFlagBits::Blacklisted; + has_blacklisted |= ScaleDown(image); + image.scale_rating = 0; } } } @@ -783,20 +781,9 @@ ImageId TextureCache

::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, return image_id; } -template -bool TextureCache

::BlackListImage(ImageId image_id) { - auto& image = slot_images[image_id]; - if (True(image.flags & ImageFlagBits::Blacklisted)) { - return false; - } - image.flags |= ImageFlagBits::Blacklisted; - ScaleDown(image); - return true; -} - template bool TextureCache

::ImageCanRescale(ImageBase& image) { - if (!image.info.rescaleable || True(image.flags & ImageFlagBits::Blacklisted)) { + if (!image.info.rescaleable) { return false; } if (Settings::values.resolution_info.downscale && !image.info.downscaleable) { diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index e210393ba..4f876b2f4 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -166,8 +166,6 @@ public: [[nodiscard]] bool IsRescaling(const ImageViewBase& image_view) const noexcept; - [[nodiscard]] bool BlackListImage(ImageId image_id); - std::mutex mutex; private: -- cgit v1.2.3 From 3b61de74e6dc7526ffa8f03c21d81e2c3566ce90 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 18 Oct 2021 22:56:36 +0200 Subject: Texture Cache: fix memory managment and optimize scaled downloads, uploads. --- .../renderer_opengl/gl_texture_cache.cpp | 24 +++++++++++++++++----- src/video_core/renderer_opengl/gl_texture_cache.h | 4 ++-- .../renderer_vulkan/vk_texture_cache.cpp | 23 +++++++++++++++++---- src/video_core/renderer_vulkan/vk_texture_cache.h | 4 ++-- src/video_core/texture_cache/image_base.cpp | 2 +- src/video_core/texture_cache/image_base.h | 6 +++--- src/video_core/texture_cache/texture_cache.h | 22 ++++++++++---------- 7 files changed, 57 insertions(+), 28 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 34d3723e5..a6e9eb60b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -697,7 +697,7 @@ void Image::UploadMemory(const ImageBufferMap& map, std::span copies) { const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); if (is_rescaled) { - ScaleDown(); + ScaleDown(true); } glBindBuffer(GL_PIXEL_UNPACK_BUFFER, map.buffer); glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, map.offset, unswizzled_size_bytes); @@ -725,6 +725,10 @@ void Image::UploadMemory(const ImageBufferMap& map, void Image::DownloadMemory(ImageBufferMap& map, std::span copies) { + const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); + if (is_rescaled) { + ScaleDown(); + } glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); // TODO: Move this to its own API glBindBuffer(GL_PIXEL_PACK_BUFFER, map.buffer); glPixelStorei(GL_PACK_ALIGNMENT, 1); @@ -743,6 +747,9 @@ void Image::DownloadMemory(ImageBufferMap& map, } CopyImageToBuffer(copy, map.offset); } + if (is_rescaled) { + ScaleUp(true); + } } GLuint Image::StorageHandle() noexcept { @@ -979,7 +986,7 @@ bool Image::Scale(bool up_scale) { return true; } -bool Image::ScaleUp() { +bool Image::ScaleUp(bool ignore) { if (True(flags & ImageFlagBits::Rescaled)) { return false; } @@ -997,7 +1004,11 @@ bool Image::ScaleUp() { flags &= ~ImageFlagBits::Rescaled; return false; } - scale_count++; + has_scaled = true; + if (ignore) { + current_texture = upscaled_backup.handle; + return true; + } if (!Scale()) { flags &= ~ImageFlagBits::Rescaled; return false; @@ -1005,7 +1016,7 @@ bool Image::ScaleUp() { return true; } -bool Image::ScaleDown() { +bool Image::ScaleDown(bool ignore) { if (False(flags & ImageFlagBits::Rescaled)) { return false; } @@ -1013,7 +1024,10 @@ bool Image::ScaleDown() { if (!runtime->resolution.active) { return false; } - scale_count++; + if (ignore) { + current_texture = texture.handle; + return true; + } if (!Scale(false)) { flags &= ~ImageFlagBits::Rescaled; return false; diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 81aaef3da..eeb5133d5 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -196,9 +196,9 @@ public: return gl_type; } - bool ScaleUp(); + bool ScaleUp(bool ignore = false); - bool ScaleDown(); + bool ScaleDown(bool ignore = false); private: void CopyBufferToImage(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 51367c01d..02aac3b98 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1055,7 +1055,7 @@ void Image::UploadMemory(const StagingBufferRef& map, std::spanRequestOutsideRenderPassOperationContext(); std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); @@ -1073,6 +1073,10 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span copies) { + const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); + if (is_rescaled) { + ScaleDown(); + } std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); scheduler->RequestOutsideRenderPassOperationContext(); scheduler->Record([buffer = map.buffer, image = *original_image, aspect_mask = aspect_mask, @@ -1125,9 +1129,12 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::spandevice; const bool is_2d = info.type == ImageType::e2D; const u32 scaled_width = resolution.ScaleUp(info.size.width); @@ -1149,8 +1156,12 @@ bool Image::ScaleUp() { scaled_image = MakeImage(device, scaled_info); auto& allocator = runtime->memory_allocator; scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal)); + ignore = false; } current_image = *scaled_image; + if (ignore) { + return true; + } if (aspect_mask == 0) { aspect_mask = ImageAspectMask(info.format); @@ -1212,7 +1223,7 @@ bool Image::ScaleUp() { return true; } -bool Image::ScaleDown() { +bool Image::ScaleDown(bool ignore) { if (False(flags & ImageFlagBits::Rescaled)) { return false; } @@ -1221,6 +1232,10 @@ bool Image::ScaleDown() { if (!resolution.active) { return false; } + if (ignore) { + current_image = *original_image; + return true; + } const auto& device = runtime->device; const bool is_2d = info.type == ImageType::e2D; const u32 scaled_width = resolution.ScaleUp(info.size.width); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index df854a20c..8dbddfaf7 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -129,9 +129,9 @@ public: return std::exchange(initialized, true); } - bool ScaleUp(); + bool ScaleUp(bool ignore = false); - bool ScaleDown(); + bool ScaleDown(bool ignore = false); private: VKScheduler* scheduler{}; diff --git a/src/video_core/texture_cache/image_base.cpp b/src/video_core/texture_cache/image_base.cpp index 3db2ec825..3db2fdf34 100644 --- a/src/video_core/texture_cache/image_base.cpp +++ b/src/video_core/texture_cache/image_base.cpp @@ -61,7 +61,7 @@ ImageBase::ImageBase(const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_ : info{info_}, guest_size_bytes{CalculateGuestSizeInBytes(info)}, unswizzled_size_bytes{CalculateUnswizzledSizeBytes(info)}, converted_size_bytes{CalculateConvertedSizeBytes(info)}, scale_rating{}, scale_tick{}, - scale_count{}, gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, + has_scaled{}, gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_}, cpu_addr_end{cpu_addr + guest_size_bytes}, mip_level_offsets{CalculateMipLevelOffsets(info)} { if (info.type == ImageType::e3D) { slice_offsets = CalculateSliceOffsets(info); diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index cd4b5f636..02c669766 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -77,8 +77,8 @@ struct ImageBase { void CheckBadOverlapState(); void CheckAliasState(); - bool HasScaled() { - return scale_count > 0; + bool HasScaled() const { + return has_scaled; } ImageInfo info; @@ -88,7 +88,7 @@ struct ImageBase { u32 converted_size_bytes = 0; u32 scale_rating = 0; u64 scale_tick = 0; - u32 scale_count = 0; + bool has_scaled = false; ImageFlagBits flags = ImageFlagBits::CpuModified; GPUVAddr gpu_addr = 0; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index c885586e8..13914dc8b 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -60,7 +60,7 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& // On OpenGL we can be more conservatives as the driver takes care. expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB; critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB; - minimum_memory = expected_memory; + minimum_memory = 0; } } @@ -1464,16 +1464,6 @@ template void TextureCache

::TrackImage(ImageBase& image, ImageId image_id) { ASSERT(False(image.flags & ImageFlagBits::Tracked)); image.flags |= ImageFlagBits::Tracked; - if (image.HasScaled()) { - total_used_memory -= GetScaledImageSizeBytes(image); - } - u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); - if ((IsPixelFormatASTC(image.info.format) && - True(image.flags & ImageFlagBits::AcceleratedUpload)) || - True(image.flags & ImageFlagBits::Converted)) { - tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); - } - total_used_memory -= Common::AlignUp(tentative_size, 1024); if (False(image.flags & ImageFlagBits::Sparse)) { rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); return; @@ -1519,6 +1509,16 @@ void TextureCache

::UntrackImage(ImageBase& image, ImageId image_id) { template void TextureCache

::DeleteImage(ImageId image_id) { ImageBase& image = slot_images[image_id]; + if (image.HasScaled()) { + total_used_memory -= GetScaledImageSizeBytes(image); + } + u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); + if ((IsPixelFormatASTC(image.info.format) && + True(image.flags & ImageFlagBits::AcceleratedUpload)) || + True(image.flags & ImageFlagBits::Converted)) { + tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); + } + total_used_memory -= Common::AlignUp(tentative_size, 1024); const GPUVAddr gpu_addr = image.gpu_addr; const auto alloc_it = image_allocs_table.find(gpu_addr); if (alloc_it == image_allocs_table.end()) { -- cgit v1.2.3 From d37d10e7a7b9037a259b27923716e5ce3084d6c3 Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Wed, 20 Oct 2021 18:27:25 +0200 Subject: TextureCache: fix rescaling in aliases and overlap joins. --- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 19 +++++------ src/video_core/texture_cache/texture_cache.h | 41 +++++++++++++++++------- src/video_core/texture_cache/util.cpp | 8 +++-- src/video_core/texture_cache/util.h | 3 +- 4 files changed, 48 insertions(+), 23 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 5ca67c413..fd334a146 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -63,7 +63,7 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in const auto conv = [scale](float value) { float new_value = value * scale; if (scale < 1.0f) { - bool sign = std::signbit(new_value); + const bool sign = std::signbit(value); new_value = std::round(std::abs(new_value)); new_value = sign ? -new_value : new_value; } @@ -96,21 +96,22 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u32 down_shift = 0) { const auto& src = regs.scissor_test[index]; VkRect2D scissor; - const auto scale_up = [&](u32 value) -> u32 { + const auto scale_up = [&](s32 value) -> s32 { if (value == 0) { return 0U; } - const u32 upset = value * up_scale; - u32 acumm = 0; + const s32 upset = value * up_scale; + s32 acumm = 0; if ((up_scale >> down_shift) == 0) { - acumm = upset & 0x1; + acumm = upset % 2; } - const u32 converted_value = (value * up_scale) >> down_shift; - return std::max(converted_value + acumm, 1U); + const s32 converted_value = (value * up_scale) >> down_shift; + return value < 0 ? std::min(converted_value - acumm, -1) + : std::max(converted_value + acumm, 1); }; if (src.enable) { - scissor.offset.x = static_cast(scale_up(src.min_x)); - scissor.offset.y = static_cast(scale_up(src.min_y)); + scissor.offset.x = scale_up(static_cast(src.min_x)); + scissor.offset.y = scale_up(static_cast(src.min_y)); scissor.extent.width = scale_up(src.max_x - src.min_x); scissor.extent.height = scale_up(src.max_y - src.min_y); } else { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 13914dc8b..a32c11d04 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1037,8 +1037,11 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA if (overlap.info.num_samples != new_image.info.num_samples) { LOG_WARNING(HW_GPU, "Copying between images with different samples is not implemented"); } else { + const auto& resolution = Settings::values.resolution_info; const SubresourceBase base = new_image.TryFindBase(overlap.gpu_addr).value(); - auto copies = MakeShrinkImageCopies(new_info, overlap.info, base); + const u32 up_scale = can_rescale ? resolution.up_scale : 1; + const u32 down_shift = can_rescale ? resolution.down_shift : 0; + auto copies = MakeShrinkImageCopies(new_info, overlap.info, base, up_scale, down_shift); runtime.CopyImage(new_image, overlap, std::move(copies)); } if (True(overlap.flags & ImageFlagBits::Tracked)) { @@ -1659,19 +1662,35 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { const ImageBase& rhs_image = slot_images[rhs->id]; return lhs_image.modification_tick < rhs_image.modification_tick; }); + const auto& resolution = Settings::values.resolution_info; for (const AliasedImage* const aliased : aliased_images) { - if (any_rescaled) { - Image& aliased_image = slot_images[aliased->id]; - if (can_rescale) { - ScaleUp(aliased_image); - } else { - ScaleDown(aliased_image); - if (any_blacklisted) { - aliased_image.flags |= ImageFlagBits::Blacklisted; - } + if (!resolution.active | !any_rescaled) { + CopyImage(image_id, aliased->id, aliased->copies); + continue; + } + Image& aliased_image = slot_images[aliased->id]; + if (!can_rescale) { + ScaleDown(aliased_image); + if (any_blacklisted) { + aliased_image.flags |= ImageFlagBits::Blacklisted; + } + CopyImage(image_id, aliased->id, aliased->copies); + continue; + } + ScaleUp(aliased_image); + + const bool both_2d{image.info.type == ImageType::e2D && + aliased_image.info.type == ImageType::e2D}; + auto copies = aliased->copies; + for (auto copy : copies) { + copy.extent.width = std::max( + (copy.extent.width * resolution.up_scale) >> resolution.down_shift, 1); + if (both_2d) { + copy.extent.height = std::max( + (copy.extent.height * resolution.up_scale) >> resolution.down_shift, 1); } } - CopyImage(image_id, aliased->id, aliased->copies); + CopyImage(image_id, aliased->id, copies); } } diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index 59cf2f561..9922aa0cc 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp @@ -723,7 +723,7 @@ ImageViewType RenderTargetImageViewType(const ImageInfo& info) noexcept { } std::vector MakeShrinkImageCopies(const ImageInfo& dst, const ImageInfo& src, - SubresourceBase base) { + SubresourceBase base, u32 up_scale, u32 down_shift) { ASSERT(dst.resources.levels >= src.resources.levels); ASSERT(dst.num_samples == src.num_samples); @@ -732,7 +732,7 @@ std::vector MakeShrinkImageCopies(const ImageInfo& dst, const ImageIn ASSERT(src.type == ImageType::e3D); ASSERT(src.resources.levels == 1); } - + const bool both_2d{src.type == ImageType::e2D && dst.type == ImageType::e2D}; std::vector copies; copies.reserve(src.resources.levels); for (s32 level = 0; level < src.resources.levels; ++level) { @@ -762,6 +762,10 @@ std::vector MakeShrinkImageCopies(const ImageInfo& dst, const ImageIn if (is_dst_3d) { copy.extent.depth = src.size.depth; } + copy.extent.width = std::max((copy.extent.width * up_scale) >> down_shift, 1); + if (both_2d) { + copy.extent.height = std::max((copy.extent.height * up_scale) >> down_shift, 1); + } } return copies; } diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h index 766502908..7af52de2e 100644 --- a/src/video_core/texture_cache/util.h +++ b/src/video_core/texture_cache/util.h @@ -55,7 +55,8 @@ struct OverlapResult { [[nodiscard]] std::vector MakeShrinkImageCopies(const ImageInfo& dst, const ImageInfo& src, - SubresourceBase base); + SubresourceBase base, u32 up_scale = 1, + u32 down_shift = 0); [[nodiscard]] bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config); -- cgit v1.2.3 From bf01b7993dca835a516abdc2142be96bc0f216ec Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Wed, 20 Oct 2021 23:21:52 +0200 Subject: TextureCache: Improve Reaper. --- src/video_core/texture_cache/texture_cache.h | 38 +++++++++++++++-------- src/video_core/texture_cache/texture_cache_base.h | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index a32c11d04..f1254ef62 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -51,8 +51,8 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& if constexpr (HAS_DEVICE_MEMORY_INFO) { const auto device_memory = runtime.GetDeviceLocalMemory(); - const u64 possible_expected_memory = (device_memory * 3) / 10; - const u64 possible_critical_memory = (device_memory * 6) / 10; + const u64 possible_expected_memory = (device_memory * 4) / 10; + const u64 possible_critical_memory = (device_memory * 7) / 10; expected_memory = std::max(possible_expected_memory, DEFAULT_EXPECTED_MEMORY); critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY); minimum_memory = 0; @@ -69,7 +69,7 @@ void TextureCache

::RunGarbageCollector() { const bool high_priority_mode = total_used_memory >= expected_memory; const bool aggressive_mode = total_used_memory >= critical_memory; const u64 ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 100ULL; - size_t num_iterations = aggressive_mode ? 10000 : (high_priority_mode ? 100 : 5); + size_t num_iterations = aggressive_mode ? 300 : (high_priority_mode ? 50 : 10); const auto clean_up = [this, &num_iterations, high_priority_mode](ImageId image_id) { if (num_iterations == 0) { return true; @@ -91,7 +91,7 @@ void TextureCache

::RunGarbageCollector() { UntrackImage(image, image_id); } UnregisterImage(image_id); - DeleteImage(image_id); + DeleteImage(image_id, image.scale_tick > frame_tick + 5); return false; }; lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, clean_up); @@ -287,7 +287,9 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; image.scale_rating = scale_rating; - image.scale_tick = frame_tick + 1; + if (image.scale_tick <= frame_tick) { + image.scale_tick = frame_tick + 1; + } } }; for (size_t index = 0; index < NUM_RT; ++index) { @@ -810,6 +812,9 @@ bool TextureCache

::ImageCanRescale(ImageBase& image) { template void TextureCache

::InvalidateScale(Image& image) { + if (image.scale_tick <= frame_tick) { + image.scale_tick = frame_tick + 1; + } const std::span image_view_ids = image.image_view_ids; auto& dirty = maxwell3d.dirty.flags; dirty[Dirty::RenderTargets] = true; @@ -842,12 +847,15 @@ void TextureCache

::InvalidateScale(Image& image) { template u64 TextureCache

::GetScaledImageSizeBytes(ImageBase& image) { - const f32 add_to_size = Settings::values.resolution_info.up_factor; - const bool sign = std::signbit(add_to_size); - const u32 image_size_bytes = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); - const u64 tentative_size = image_size_bytes * static_cast(std::abs(add_to_size)); + const u64 scale_up = static_cast(Settings::values.resolution_info.up_scale * + Settings::values.resolution_info.up_scale); + const u64 down_shift = static_cast(Settings::values.resolution_info.down_shift + + Settings::values.resolution_info.down_shift); + const u64 image_size_bytes = + static_cast(std::max(image.guest_size_bytes, image.unswizzled_size_bytes)); + const u64 tentative_size = (image_size_bytes * scale_up) >> down_shift; const u64 fitted_size = Common::AlignUp(tentative_size, 1024); - return sign ? -fitted_size : fitted_size; + return fitted_size; } template @@ -1510,7 +1518,7 @@ void TextureCache

::UntrackImage(ImageBase& image, ImageId image_id) { } template -void TextureCache

::DeleteImage(ImageId image_id) { +void TextureCache

::DeleteImage(ImageId image_id, bool immediate_delete) { ImageBase& image = slot_images[image_id]; if (image.HasScaled()) { total_used_memory -= GetScaledImageSizeBytes(image); @@ -1576,10 +1584,14 @@ void TextureCache

::DeleteImage(ImageId image_id) { num_removed_overlaps); } for (const ImageViewId image_view_id : image_view_ids) { - sentenced_image_view.Push(std::move(slot_image_views[image_view_id])); + if (!immediate_delete) { + sentenced_image_view.Push(std::move(slot_image_views[image_view_id])); + } slot_image_views.erase(image_view_id); } - sentenced_images.Push(std::move(slot_images[image_id])); + if (!immediate_delete) { + sentenced_images.Push(std::move(slot_images[image_id])); + } slot_images.erase(image_id); alloc_images.erase(alloc_image_it); diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 4f876b2f4..eea589269 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -292,7 +292,7 @@ private: void UntrackImage(ImageBase& image, ImageId image_id); /// Delete image from the cache - void DeleteImage(ImageId image); + void DeleteImage(ImageId image, bool immediate_delete = false); /// Remove image views references from the cache void RemoveImageViewReferences(std::span removed_views); -- cgit v1.2.3 From 6cdfaee7b4f3f68310e9cca755482e3e6993da10 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 21 Oct 2021 21:31:33 +0200 Subject: Texture Cache: Fix blitting. --- src/video_core/texture_cache/util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index 9922aa0cc..ddc9fb13a 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp @@ -1157,10 +1157,10 @@ void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { dst_info.format = dst->info.format; } - if (!dst && src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { + if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) { dst_info.format = src->info.format; } - if (!src && dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { + if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) { src_info.format = dst->info.format; } } -- cgit v1.2.3 From 5c6fa8893589fd70bc743c0d0b77c0c375b24bd3 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 23 Oct 2021 01:52:34 +0200 Subject: OpenGlTextureCache: Fix state invalidation on rescaling. --- src/video_core/renderer_opengl/gl_texture_cache.cpp | 11 +++++++++++ src/video_core/renderer_opengl/gl_texture_cache.h | 4 ++++ src/video_core/texture_cache/texture_cache.h | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index a6e9eb60b..6e7f66ef0 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -942,10 +942,21 @@ bool Image::Scale(bool up_scale) { dst_info.size.height = scaled_height; upscaled_backup = MakeImage(dst_info, gl_internal_format); } + auto& state_tracker = runtime->GetStateTracker(); + state_tracker.NotifyViewport0(); + state_tracker.NotifyScissor0(); // TODO (ameerj): Investigate other GL states that affect blitting. GLboolean scissor_test; glGetBooleani_v(GL_SCISSOR_TEST, 0, &scissor_test); glDisablei(GL_SCISSOR_TEST, 0); + if (up_scale) { + glViewportIndexedf(0, 0.0f, 0.0f, static_cast(scaled_width), + static_cast(scaled_height)); + } else { + glViewportIndexedf(0, 0.0f, 0.0f, static_cast(original_width), + static_cast(original_height)); + } + const GLuint read_fbo = runtime->rescale_read_fbos[fbo_index].handle; const GLuint draw_fbo = runtime->rescale_draw_fbos[fbo_index].handle; diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index eeb5133d5..8161e6b72 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -116,6 +116,10 @@ public: void TickFrame() {} + StateTracker& GetStateTracker() { + return state_tracker; + } + private: struct StagingBuffers { explicit StagingBuffers(GLenum storage_flags_, GLenum map_flags_); diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index f1254ef62..dd9553806 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1810,8 +1810,8 @@ void TextureCache

::BindRenderTarget(ImageViewId* old_id, ImageViewId new_id) if (*old_id == new_id) { return; } - if (*old_id) { - const ImageViewBase& old_view = slot_image_views[*old_id]; + if (new_id) { + const ImageViewBase& old_view = slot_image_views[new_id]; if (True(old_view.flags & ImageViewFlagBits::PreemtiveDownload)) { uncommitted_downloads.push_back(old_view.image_id); } -- cgit v1.2.3 From 099b0b3167d6dc47b764331f40aa935e8a9ef86a Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Sat, 23 Oct 2021 17:17:02 +0200 Subject: Texture Cache: Fix memory usage on ScaleDown. --- src/video_core/texture_cache/texture_cache.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index dd9553806..26ab857c9 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -878,10 +878,6 @@ bool TextureCache

::ScaleDown(Image& image) { if (!rescaled) { return false; } - const bool has_copy = image.HasScaled(); - if (!has_copy) { - total_used_memory -= GetScaledImageSizeBytes(image); - } InvalidateScale(image); return true; } -- cgit v1.2.3 From 917b2466ad996cae75d9a0ca31226597b256acf9 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sun, 24 Oct 2021 23:07:15 -0400 Subject: texture_cache: Refactor Render Target scaling function --- src/video_core/texture_cache/texture_cache.h | 33 +++++++++++++---------- src/video_core/texture_cache/texture_cache_base.h | 5 ++++ 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 26ab857c9..c8031b695 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -192,19 +192,8 @@ void TextureCache

::SynchronizeComputeDescriptors() { } template -void TextureCache

::UpdateRenderTargets(bool is_clear) { - using namespace VideoCommon::Dirty; +bool TextureCache

::RescaleRenderTargets(bool is_clear) { auto& flags = maxwell3d.dirty.flags; - if (!flags[Dirty::RenderTargets]) { - for (size_t index = 0; index < NUM_RT; ++index) { - ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; - PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id)); - } - const ImageViewId depth_buffer_id = render_targets.depth_buffer_id; - PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id)); - return; - } - u32 scale_rating = 0; bool rescaled = false; std::array tmp_color_images{}; @@ -281,8 +270,6 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { scale_rating = 1; } } while (has_deleted_images); - // Rescale End - const auto set_rating = [this, scale_rating](ImageId image_id) { if (image_id != CORRUPT_ID) { Image& image = slot_images[image_id]; @@ -297,6 +284,24 @@ void TextureCache

::UpdateRenderTargets(bool is_clear) { } set_rating(tmp_depth_image); + return rescaled; +} + +template +void TextureCache

::UpdateRenderTargets(bool is_clear) { + using namespace VideoCommon::Dirty; + auto& flags = maxwell3d.dirty.flags; + if (!flags[Dirty::RenderTargets]) { + for (size_t index = 0; index < NUM_RT; ++index) { + ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index]; + PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id)); + } + const ImageViewId depth_buffer_id = render_targets.depth_buffer_id; + PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id)); + return; + } + + const bool rescaled = RescaleRenderTargets(is_clear); if (is_rescaling != rescaled) { flags[Dirty::RescaleViewports] = true; flags[Dirty::RescaleScissors] = true; diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index eea589269..643ad811c 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -119,6 +119,11 @@ public: /// Refresh the state for compute image view and sampler descriptors void SynchronizeComputeDescriptors(); + /// Updates the Render Targets if they can be rescaled + /// @param is_clear True when the render targets are being used for clears + /// @retval True if the Render Targets have been rescaled. + bool RescaleRenderTargets(bool is_clear); + /// Update bound render targets and upload memory if necessary /// @param is_clear True when the render targets are being used for clears void UpdateRenderTargets(bool is_clear); -- cgit v1.2.3 From de1c8c5c2c3131bb122351e676014cdc7c442e78 Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Fri, 29 Oct 2021 17:02:57 +0200 Subject: Texture Cahe/Shader decompiler: Resize PointSize on rescaling, refactor and make reaper more agressive on 4Gb GPUs. --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 21 +++++++++++++++++++++ src/video_core/renderer_opengl/gl_rasterizer.cpp | 5 +++-- src/video_core/texture_cache/image_base.h | 1 - src/video_core/texture_cache/image_info.cpp | 6 +++--- src/video_core/texture_cache/texture_cache.h | 18 ++---------------- 5 files changed, 29 insertions(+), 22 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index a5fa4ee83..81098c038 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -75,6 +75,14 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { inst.ReplaceUsesWith(downscaled_frag_coord); } +void PatchPointSize(IR::Block& block, IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const IR::F32 point_value{inst.Arg(1)}; + const IR::F32 up_factor{ir.FPRecip(ir.ResolutionDownFactor())}; + const IR::F32 upscaled_point_value{ir.FPMul(point_value, up_factor)}; + inst.SetArg(1, upscaled_point_value); +} + [[nodiscard]] IR::U32 Scale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value) { IR::U32 scaled_value{value}; if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { @@ -253,6 +261,19 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { } break; } + case IR::Opcode::SetAttribute: { + const IR::Attribute attr{inst.Arg(0).Attribute()}; + switch (attr) { + case IR::Attribute::PointSize: + if (inst.Flags() != 0xDEADBEEF) { + PatchPointSize(block, inst); + } + break; + default: + break; + } + break; + } case IR::Opcode::ImageQueryDimensions: PatchImageQueryDimensions(block, inst); break; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d8ac46d2a..9b516c64f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -976,8 +976,9 @@ void RasterizerOpenGL::SyncPointState() { oglEnable(GL_POINT_SPRITE, maxwell3d.regs.point_sprite_enable); oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d.regs.vp_point_size.enable); - - glPointSize(std::max(1.0f, maxwell3d.regs.point_size)); + const bool is_rescaling{texture_cache.IsRescaling()}; + const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; + glPointSize(std::max(1.0f, maxwell3d.regs.point_size * scale)); } void RasterizerOpenGL::SyncLineState() { diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 02c669766..89c111c00 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -38,7 +38,6 @@ enum class ImageFlagBits : u32 { Rescaled = 1 << 12, CheckingRescalable = 1 << 13, IsRescalable = 1 << 14, - Blacklisted = 1 << 15, }; DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index d8e414247..015a2d33d 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -135,7 +135,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) type = ImageType::e3D; size.depth = rt.depth; } else { - rescaleable = block.depth == 0 && size.height > 256; + rescaleable = block.depth == 0; downscaleable = size.height > 512; type = ImageType::e2D; resources.layers = rt.depth; @@ -165,7 +165,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept { type = ImageType::e3D; size.depth = regs.zeta_depth; } else { - rescaleable = block.depth == 0 && size.height > 256; + rescaleable = block.depth == 0; downscaleable = size.height > 512; type = ImageType::e2D; resources.layers = regs.zeta_depth; @@ -199,7 +199,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { .height = config.height, .depth = 1, }; - rescaleable = block.depth == 0 && size.height > 256; + rescaleable = block.depth == 0; downscaleable = size.height > 512; } } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index c8031b695..aec130a32 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -53,8 +53,8 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& const auto device_memory = runtime.GetDeviceLocalMemory(); const u64 possible_expected_memory = (device_memory * 4) / 10; const u64 possible_critical_memory = (device_memory * 7) / 10; - expected_memory = std::max(possible_expected_memory, DEFAULT_EXPECTED_MEMORY); - critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY); + expected_memory = std::max(possible_expected_memory, DEFAULT_EXPECTED_MEMORY - 256_MiB); + critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY - 512_MiB); minimum_memory = 0; } else { // On OpenGL we can be more conservatives as the driver takes care. @@ -355,7 +355,6 @@ void TextureCache

::FillImageViews(DescriptorTable& table, if (view.blacklist && view.id != NULL_IMAGE_VIEW_ID) { const ImageViewBase& image_view{slot_image_views[view.id]}; auto& image = slot_images[image_view.image_id]; - image.flags |= ImageFlagBits::Blacklisted; has_blacklisted |= ScaleDown(image); image.scale_rating = 0; } @@ -985,7 +984,6 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA bool can_rescale = info.rescaleable; bool any_rescaled = false; - bool any_blacklisted = false; for (const ImageId sibling_id : all_siblings) { if (!can_rescale) { break; @@ -993,7 +991,6 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA Image& sibling = slot_images[sibling_id]; can_rescale &= ImageCanRescale(sibling); any_rescaled |= True(sibling.flags & ImageFlagBits::Rescaled); - any_blacklisted |= True(sibling.flags & ImageFlagBits::Blacklisted); } can_rescale &= any_rescaled; @@ -1007,9 +1004,6 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA for (const ImageId sibling_id : all_siblings) { Image& sibling = slot_images[sibling_id]; ScaleDown(sibling); - if (any_blacklisted) { - sibling.flags |= ImageFlagBits::Blacklisted; - } } } @@ -1644,7 +1638,6 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { boost::container::small_vector aliased_images; Image& image = slot_images[image_id]; bool any_rescaled = True(image.flags & ImageFlagBits::Rescaled); - bool any_blacklisted = True(image.flags & ImageFlagBits::Blacklisted); u64 most_recent_tick = image.modification_tick; for (const AliasedImage& aliased : image.aliased_images) { ImageBase& aliased_image = slot_images[aliased.id]; @@ -1652,7 +1645,6 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { most_recent_tick = std::max(most_recent_tick, aliased_image.modification_tick); aliased_images.push_back(&aliased); any_rescaled |= True(aliased_image.flags & ImageFlagBits::Rescaled); - any_blacklisted |= True(aliased_image.flags & ImageFlagBits::Blacklisted); } } if (aliased_images.empty()) { @@ -1664,9 +1656,6 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { ScaleUp(image); } else { ScaleDown(image); - if (any_blacklisted) { - image.flags |= ImageFlagBits::Blacklisted; - } } } image.modification_tick = most_recent_tick; @@ -1684,9 +1673,6 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { Image& aliased_image = slot_images[aliased->id]; if (!can_rescale) { ScaleDown(aliased_image); - if (any_blacklisted) { - aliased_image.flags |= ImageFlagBits::Blacklisted; - } CopyImage(image_id, aliased->id, aliased->copies); continue; } -- cgit v1.2.3 From 6c97ab571a3d169d1d2a5472040d4373ea61184d Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 30 Oct 2021 01:50:32 +0200 Subject: Texture Cache: revert Image changes. --- src/video_core/texture_cache/image_info.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 015a2d33d..afb94082b 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -16,6 +16,7 @@ namespace VideoCommon { using Tegra::Texture::TextureType; using Tegra::Texture::TICEntry; using VideoCore::Surface::PixelFormat; +using VideoCore::Surface::SurfaceType; ImageInfo::ImageInfo(const TICEntry& config) noexcept { format = PixelFormatFromTextureInfo(config.format, config.r_type, config.g_type, config.b_type, @@ -102,6 +103,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { layer_stride = CalculateLayerStride(*this); maybe_unaligned_layer_stride = CalculateLayerSize(*this); rescaleable &= (block.depth == 0) && resources.levels == 1; + rescaleable &= size.height > 256 || GetFormatType(format) != SurfaceType::ColorTexture; downscaleable = size.height > 512; } } @@ -136,6 +138,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) size.depth = rt.depth; } else { rescaleable = block.depth == 0; + rescaleable &= size.height > 256; downscaleable = size.height > 512; type = ImageType::e2D; resources.layers = rt.depth; @@ -200,6 +203,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { .depth = 1, }; rescaleable = block.depth == 0; + rescaleable &= size.height > 256; downscaleable = size.height > 512; } } -- cgit v1.2.3 From 978f598ff64d3bd0299d06c47e6cbd63a496122c Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 17 Nov 2021 00:59:46 +0100 Subject: TextureCache: Fix OGL cleaning --- src/video_core/renderer_opengl/gl_texture_cache.cpp | 4 ++++ src/video_core/renderer_opengl/gl_texture_cache.h | 16 ++++++++++++++++ src/video_core/renderer_vulkan/vk_texture_cache.cpp | 4 ++++ src/video_core/renderer_vulkan/vk_texture_cache.h | 16 ++++++++++++++++ src/video_core/texture_cache/texture_cache.h | 3 +++ 5 files changed, 43 insertions(+) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 1d3f193af..30dfcfa6a 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -1117,6 +1117,8 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params) : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} +ImageView::~ImageView() = default; + GLuint ImageView::StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format) { if (image_format == Shader::ImageFormat::Typeless) { return Handle(texture_type); @@ -1272,6 +1274,8 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span copies) { static constexpr VideoCommon::Offset3D zero_offset{0, 0, 0}; diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index c51a7428d..a717cf8c8 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -232,6 +232,14 @@ public: const VideoCommon::ImageViewInfo& view_info); explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); + ~ImageView(); + + ImageView(const ImageView&) = delete; + ImageView& operator=(const ImageView&) = delete; + + ImageView(ImageView&&) = default; + ImageView& operator=(ImageView&&) = default; + [[nodiscard]] GLuint StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format); @@ -300,6 +308,14 @@ public: explicit Framebuffer(TextureCacheRuntime&, std::span color_buffers, ImageView* depth_buffer, const VideoCommon::RenderTargets& key); + ~Framebuffer(); + + Framebuffer(const Framebuffer&) = delete; + Framebuffer& operator=(const Framebuffer&) = delete; + + Framebuffer(Framebuffer&&) = default; + Framebuffer& operator=(Framebuffer&&) = default; + [[nodiscard]] GLuint Handle() const noexcept { return framebuffer.handle; } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index daf26f380..407fd2a15 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1366,6 +1366,8 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams& params) : VideoCommon::ImageViewBase{params} {} +ImageView::~ImageView() = default; + VkImageView ImageView::DepthView() { if (depth_view) { return *depth_view; @@ -1492,6 +1494,8 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, CreateFramebuffer(runtime, color_buffers, depth_buffer); } +Framebuffer::~Framebuffer() = default; + void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, std::span color_buffers, ImageView* depth_buffer) { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 9d149d306..ff28b4e96 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -162,6 +162,14 @@ public: const VideoCommon::ImageViewInfo&, GPUVAddr); explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); + ~ImageView(); + + ImageView(const ImageView&) = delete; + ImageView& operator=(const ImageView&) = delete; + + ImageView(ImageView&&) = default; + ImageView& operator=(ImageView&&) = default; + [[nodiscard]] VkImageView DepthView(); [[nodiscard]] VkImageView StencilView(); @@ -235,6 +243,14 @@ public: explicit Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, ImageView* depth_buffer, VkExtent2D extent); + ~Framebuffer(); + + Framebuffer(const Framebuffer&) = delete; + Framebuffer& operator=(const Framebuffer&) = delete; + + Framebuffer(Framebuffer&&) = default; + Framebuffer& operator=(Framebuffer&&) = default; + void CreateFramebuffer(TextureCacheRuntime& runtime, std::span color_buffers, ImageView* depth_buffer); diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index aec130a32..4d2874bf2 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1620,6 +1620,9 @@ void TextureCache

::RemoveFramebuffers(std::span removed_vi auto it = framebuffers.begin(); while (it != framebuffers.end()) { if (it->first.Contains(removed_views)) { + auto framebuffer_id = it->second; + ASSERT(framebuffer_id); + sentenced_framebuffers.Push(std::move(slot_framebuffers[framebuffer_id])); it = framebuffers.erase(it); } else { ++it; -- cgit v1.2.3