2
1
Fork 0
mirror of https://github.com/yuzu-emu/yuzu.git synced 2024-07-04 23:31:19 +01:00

vk_texture_cache: Simplify scaled image management

This commit is contained in:
ameerj 2021-09-21 22:22:24 -04:00 committed by Fernando Sahmkow
parent 8183142cd4
commit 36f261edef
2 changed files with 34 additions and 107 deletions

View file

@ -996,17 +996,14 @@ u64 TextureCacheRuntime::GetDeviceLocalMemory() const {
return device.GetDeviceLocalMemory(); return device.GetDeviceLocalMemory();
} }
void TextureCacheRuntime::TickFrame() { void TextureCacheRuntime::TickFrame() {}
prescaled_images.Tick();
prescaled_commits.Tick();
}
Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu_addr_, Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu_addr_,
VAddr cpu_addr_) VAddr cpu_addr_)
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime_.scheduler}, : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime_.scheduler},
image(MakeImage(runtime_.device, info)), runtime{&runtime_}, original_image(MakeImage(runtime_.device, info)),
commit(runtime_.memory_allocator.Commit(image, MemoryUsage::DeviceLocal)), commit(runtime_.memory_allocator.Commit(original_image, MemoryUsage::DeviceLocal)),
aspect_mask(ImageAspectMask(info.format)), runtime{&runtime_} { aspect_mask(ImageAspectMask(info.format)) {
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) { if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
if (Settings::values.accelerate_astc.GetValue()) { if (Settings::values.accelerate_astc.GetValue()) {
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload; flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
@ -1015,13 +1012,14 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
} }
} }
if (runtime->device.HasDebuggingToolAttached()) { if (runtime->device.HasDebuggingToolAttached()) {
image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
} }
static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.usage = VK_IMAGE_USAGE_STORAGE_BIT, .usage = VK_IMAGE_USAGE_STORAGE_BIT,
}; };
current_image = *original_image;
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) { if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
const auto& device = runtime->device.GetLogical(); const auto& device = runtime->device.GetLogical();
storage_image_views.reserve(info.resources.levels); storage_image_views.reserve(info.resources.levels);
@ -1030,7 +1028,7 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = &storage_image_view_usage_create_info, .pNext = &storage_image_view_usage_create_info,
.flags = 0, .flags = 0,
.image = *image, .image = *original_image,
.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32, .format = VK_FORMAT_A8B8G8R8_UNORM_PACK32,
.components{ .components{
@ -1059,12 +1057,12 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImag
// TODO: Move this to another API // TODO: Move this to another API
const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); const bool is_rescaled = True(flags & ImageFlagBits::Rescaled);
if (is_rescaled) { if (is_rescaled) {
ScaleDown(true); ScaleDown();
} }
scheduler->RequestOutsideRenderPassOperationContext(); scheduler->RequestOutsideRenderPassOperationContext();
std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask);
const VkBuffer src_buffer = map.buffer; const VkBuffer src_buffer = map.buffer;
const VkImage vk_image = *image; const VkImage vk_image = *original_image;
const VkImageAspectFlags vk_aspect_mask = aspect_mask; const VkImageAspectFlags vk_aspect_mask = aspect_mask;
const bool is_initialized = std::exchange(initialized, true); const bool is_initialized = std::exchange(initialized, true);
scheduler->Record([src_buffer, vk_image, vk_aspect_mask, is_initialized, scheduler->Record([src_buffer, vk_image, vk_aspect_mask, is_initialized,
@ -1072,18 +1070,14 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImag
CopyBufferToImage(cmdbuf, src_buffer, vk_image, vk_aspect_mask, is_initialized, vk_copies); CopyBufferToImage(cmdbuf, src_buffer, vk_image, vk_aspect_mask, is_initialized, vk_copies);
}); });
if (is_rescaled) { if (is_rescaled) {
ScaleUp(true); ScaleUp();
} }
} }
void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) {
const bool is_rescaled = True(flags & ImageFlagBits::Rescaled);
if (is_rescaled) {
ScaleDown(true);
}
std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask);
scheduler->RequestOutsideRenderPassOperationContext(); scheduler->RequestOutsideRenderPassOperationContext();
scheduler->Record([buffer = map.buffer, image = *image, aspect_mask = aspect_mask, scheduler->Record([buffer = map.buffer, image = *original_image, aspect_mask = aspect_mask,
vk_copies](vk::CommandBuffer cmdbuf) { vk_copies](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier read_barrier{ const VkImageMemoryBarrier read_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -1133,51 +1127,31 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
0, memory_write_barrier, nullptr, image_write_barrier); 0, memory_write_barrier, nullptr, image_write_barrier);
}); });
if (is_rescaled) {
SwapBackup();
}
} }
bool Image::ScaleUp(bool save_as_backup) { bool Image::ScaleUp() {
if (True(flags & ImageFlagBits::Rescaled)) { if (True(flags & ImageFlagBits::Rescaled)) {
return false; return false;
} }
ASSERT(info.type != ImageType::Linear); ASSERT(info.type != ImageType::Linear);
scaling_count++;
flags |= ImageFlagBits::Rescaled; flags |= ImageFlagBits::Rescaled;
const auto& resolution = runtime->resolution; const auto& resolution = runtime->resolution;
if (!resolution.active) { if (!resolution.active) {
return true; return true;
} }
vk::Image rescaled_image = const auto& device = runtime->device;
has_backup ? std::move(backup_image) if (!scaled_image) {
: MakeImage(runtime->device, info, resolution.up_scale, resolution.down_shift); scaled_image = MakeImage(device, info, resolution.up_scale, resolution.down_shift);
MemoryCommit new_commit = has_backup ? std::move(backup_commit) auto& allocator = runtime->memory_allocator;
: MemoryCommit(runtime->memory_allocator.Commit( scaled_commit = MemoryCommit(allocator.Commit(scaled_image, MemoryUsage::DeviceLocal));
rescaled_image, MemoryUsage::DeviceLocal)); }
has_backup = false;
if (aspect_mask == 0) { if (aspect_mask == 0) {
aspect_mask = ImageAspectMask(info.format); aspect_mask = ImageAspectMask(info.format);
} }
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 PixelFormat format = StorageFormat(info.format);
const auto format_info = const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format);
MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, false, format); const auto similar = device.GetSupportedFormat(
const auto similar = runtime->device.GetSupportedFormat(
format_info.format, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT), format_info.format, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT),
FormatType::Optimal); FormatType::Optimal);
@ -1187,55 +1161,18 @@ bool Image::ScaleUp(bool save_as_backup) {
if (aspect_mask == 0) { if (aspect_mask == 0) {
aspect_mask = ImageAspectMask(info.format); aspect_mask = ImageAspectMask(info.format);
} }
BlitScale(*scheduler, *image, *rescaled_image, info, aspect_mask, resolution, true); BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution, true);
current_image = *scaled_image;
return true; return true;
} }
void Image::SwapBackup() { bool Image::ScaleDown() {
if (!runtime->resolution.active) {
return;
}
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)) { if (False(flags & ImageFlagBits::Rescaled)) {
return false; return false;
} }
ASSERT(info.type != ImageType::Linear); ASSERT(info.type != ImageType::Linear);
flags &= ~ImageFlagBits::Rescaled; flags &= ~ImageFlagBits::Rescaled;
scaling_count++; current_image = *original_image;
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return true;
}
vk::Image downscaled_image =
has_backup ? std::move(backup_image) : MakeImage(runtime->device, info);
MemoryCommit new_commit = has_backup ? std::move(backup_commit)
: MemoryCommit(runtime->memory_allocator.Commit(
downscaled_image, MemoryUsage::DeviceLocal));
has_backup = false;
if (aspect_mask == 0) {
aspect_mask = ImageAspectMask(info.format);
}
BlitScale(*scheduler, *image, *downscaled_image, info, aspect_mask, resolution, false);
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; return true;
} }

View file

@ -8,7 +8,6 @@
#include "common/settings.h" #include "common/settings.h"
#include "shader_recompiler/shader_info.h" #include "shader_recompiler/shader_info.h"
#include "video_core/delayed_destruction_ring.h"
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
#include "video_core/texture_cache/image_view_base.h" #include "video_core/texture_cache/image_view_base.h"
#include "video_core/texture_cache/texture_cache_base.h" #include "video_core/texture_cache/texture_cache_base.h"
@ -17,7 +16,6 @@
namespace Vulkan { namespace Vulkan {
using VideoCommon::DelayedDestructionRing;
using VideoCommon::ImageId; using VideoCommon::ImageId;
using VideoCommon::NUM_RT; using VideoCommon::NUM_RT;
using VideoCommon::Region2D; using VideoCommon::Region2D;
@ -36,8 +34,6 @@ class VKScheduler;
class TextureCacheRuntime { class TextureCacheRuntime {
public: public:
static constexpr size_t TICKS_TO_DESTROY = 6;
explicit TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_, explicit TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_,
MemoryAllocator& memory_allocator_, MemoryAllocator& memory_allocator_,
StagingBufferPool& staging_buffer_pool_, StagingBufferPool& staging_buffer_pool_,
@ -90,9 +86,6 @@ public:
BlitImageHelper& blit_image_helper; BlitImageHelper& blit_image_helper;
ASTCDecoderPass& astc_decoder_pass; ASTCDecoderPass& astc_decoder_pass;
RenderPassCache& render_pass_cache; RenderPassCache& render_pass_cache;
DelayedDestructionRing<vk::Image, TICKS_TO_DESTROY> prescaled_images;
DelayedDestructionRing<MemoryCommit, TICKS_TO_DESTROY> prescaled_commits;
Settings::ResolutionScalingInfo resolution; Settings::ResolutionScalingInfo resolution;
}; };
@ -117,7 +110,7 @@ public:
std::span<const VideoCommon::BufferImageCopy> copies); std::span<const VideoCommon::BufferImageCopy> copies);
[[nodiscard]] VkImage Handle() const noexcept { [[nodiscard]] VkImage Handle() const noexcept {
return *image; return current_image;
} }
[[nodiscard]] VkImageAspectFlags AspectMask() const noexcept { [[nodiscard]] VkImageAspectFlags AspectMask() const noexcept {
@ -133,25 +126,22 @@ public:
return std::exchange(initialized, true); return std::exchange(initialized, true);
} }
bool ScaleUp(bool save_as_backup = false); bool ScaleUp();
bool ScaleDown(bool save_as_backup = false); bool ScaleDown();
void SwapBackup();
private: private:
VKScheduler* scheduler; VKScheduler* scheduler{};
vk::Image image; TextureCacheRuntime* runtime{};
vk::Image original_image;
MemoryCommit commit; MemoryCommit commit;
vk::ImageView image_view;
std::vector<vk::ImageView> storage_image_views; std::vector<vk::ImageView> storage_image_views;
VkImageAspectFlags aspect_mask = 0; VkImageAspectFlags aspect_mask = 0;
bool initialized = false; bool initialized = false;
TextureCacheRuntime* runtime; vk::Image scaled_image{};
u32 scaling_count{}; MemoryCommit scaled_commit{};
vk::Image backup_image{}; VkImage current_image{};
MemoryCommit backup_commit{};
bool has_backup{};
}; };
class ImageView : public VideoCommon::ImageViewBase { class ImageView : public VideoCommon::ImageViewBase {