2020-01-14 00:36:03 +01:00
|
|
|
// Copyright 2019 yuzu Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
#include <span>
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-07-18 18:40:14 +02:00
|
|
|
#include "common/settings.h"
|
2021-04-09 06:45:39 +02:00
|
|
|
#include "shader_recompiler/shader_info.h"
|
2021-07-18 18:40:14 +02:00
|
|
|
#include "video_core/delayed_destruction_ring.h"
|
2021-01-17 00:48:58 +01:00
|
|
|
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
|
2021-10-01 06:57:02 +02:00
|
|
|
#include "video_core/texture_cache/image_view_base.h"
|
2021-08-05 22:46:24 +02:00
|
|
|
#include "video_core/texture_cache/texture_cache_base.h"
|
2021-01-03 22:17:57 +01:00
|
|
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
2020-12-25 01:30:11 +01:00
|
|
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
2020-01-14 00:36:03 +01:00
|
|
|
|
|
|
|
namespace Vulkan {
|
|
|
|
|
2021-07-18 18:40:14 +02:00
|
|
|
using VideoCommon::DelayedDestructionRing;
|
2020-12-30 06:25:23 +01:00
|
|
|
using VideoCommon::ImageId;
|
|
|
|
using VideoCommon::NUM_RT;
|
2021-05-08 04:14:21 +02:00
|
|
|
using VideoCommon::Region2D;
|
2020-12-30 06:25:23 +01:00
|
|
|
using VideoCommon::RenderTargets;
|
|
|
|
using VideoCore::Surface::PixelFormat;
|
|
|
|
|
2021-02-13 22:49:24 +01:00
|
|
|
class ASTCDecoderPass;
|
2020-12-30 06:25:23 +01:00
|
|
|
class BlitImageHelper;
|
2020-12-26 05:10:53 +01:00
|
|
|
class Device;
|
2020-12-30 06:25:23 +01:00
|
|
|
class Image;
|
|
|
|
class ImageView;
|
|
|
|
class Framebuffer;
|
2021-03-19 23:28:31 +01:00
|
|
|
class RenderPassCache;
|
2020-12-31 02:58:05 +01:00
|
|
|
class StagingBufferPool;
|
|
|
|
class VKScheduler;
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-07-28 07:47:06 +02:00
|
|
|
class TextureCacheRuntime {
|
|
|
|
public:
|
2021-07-18 18:40:14 +02:00
|
|
|
static constexpr size_t TICKS_TO_DESTROY = 6;
|
|
|
|
|
2021-07-28 07:47:06 +02:00
|
|
|
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_);
|
2020-12-30 06:25:23 +01:00
|
|
|
|
|
|
|
void Finish();
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-04-07 01:14:55 +02:00
|
|
|
StagingBufferRef UploadStagingBuffer(size_t size);
|
2020-12-30 06:25:23 +01:00
|
|
|
|
2021-04-07 01:14:55 +02:00
|
|
|
StagingBufferRef DownloadStagingBuffer(size_t size);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-07-28 07:47:06 +02:00
|
|
|
void TickFrame();
|
|
|
|
|
|
|
|
u64 GetDeviceLocalMemory() const;
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
|
2021-05-08 04:14:21 +02:00
|
|
|
const Region2D& dst_region, const Region2D& src_region,
|
2020-12-30 06:25:23 +01:00
|
|
|
Tegra::Engines::Fermi2D::Filter filter,
|
|
|
|
Tegra::Engines::Fermi2D::Operation operation);
|
|
|
|
|
|
|
|
void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
|
|
|
|
|
|
|
|
void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view);
|
|
|
|
|
2021-04-07 01:14:55 +02:00
|
|
|
bool CanAccelerateImageUpload(Image&) const noexcept {
|
2020-12-30 06:25:23 +01:00
|
|
|
return false;
|
2020-01-14 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
2021-01-16 20:20:18 +01:00
|
|
|
void AccelerateImageUpload(Image&, const StagingBufferRef&,
|
2021-02-13 22:49:24 +01:00
|
|
|
std::span<const VideoCommon::SwizzleParameters>);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
void InsertUploadMemoryBarrier() {}
|
2021-01-04 05:56:44 +01:00
|
|
|
|
|
|
|
bool HasBrokenTextureViewFormats() const noexcept {
|
|
|
|
// No known Vulkan driver has broken image views
|
|
|
|
return false;
|
|
|
|
}
|
2021-03-04 20:12:25 +01:00
|
|
|
|
|
|
|
bool HasNativeBgr() const noexcept {
|
|
|
|
// All known Vulkan drivers can natively handle BGR textures
|
|
|
|
return true;
|
|
|
|
}
|
2021-06-17 00:29:48 +02:00
|
|
|
|
2021-07-28 07:47:06 +02:00
|
|
|
const Device& device;
|
|
|
|
VKScheduler& scheduler;
|
|
|
|
MemoryAllocator& memory_allocator;
|
|
|
|
StagingBufferPool& staging_buffer_pool;
|
|
|
|
BlitImageHelper& blit_image_helper;
|
|
|
|
ASTCDecoderPass& astc_decoder_pass;
|
|
|
|
RenderPassCache& render_pass_cache;
|
2021-07-18 18:40:14 +02:00
|
|
|
|
2021-07-28 07:47:06 +02:00
|
|
|
DelayedDestructionRing<vk::Image, TICKS_TO_DESTROY> prescaled_images;
|
|
|
|
DelayedDestructionRing<MemoryCommit, TICKS_TO_DESTROY> prescaled_commits;
|
|
|
|
Settings::ResolutionScalingInfo resolution;
|
2020-12-30 06:25:23 +01:00
|
|
|
};
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
class Image : public VideoCommon::ImageBase {
|
|
|
|
public:
|
|
|
|
explicit Image(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr,
|
|
|
|
VAddr cpu_addr);
|
2021-07-28 07:47:06 +02:00
|
|
|
explicit Image(const VideoCommon::NullImageParams&);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-06-20 17:07:17 +02:00
|
|
|
~Image();
|
|
|
|
|
|
|
|
Image(const Image&) = delete;
|
|
|
|
Image& operator=(const Image&) = delete;
|
|
|
|
|
|
|
|
Image(Image&&) = default;
|
|
|
|
Image& operator=(Image&&) = default;
|
|
|
|
|
2021-01-16 20:20:18 +01:00
|
|
|
void UploadMemory(const StagingBufferRef& map,
|
2020-12-30 06:25:23 +01:00
|
|
|
std::span<const VideoCommon::BufferImageCopy> copies);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-01-16 20:20:18 +01:00
|
|
|
void DownloadMemory(const StagingBufferRef& map,
|
2020-12-30 06:25:23 +01:00
|
|
|
std::span<const VideoCommon::BufferImageCopy> copies);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkImage Handle() const noexcept {
|
|
|
|
return *image;
|
|
|
|
}
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-02-13 22:08:50 +01:00
|
|
|
[[nodiscard]] VkImageAspectFlags AspectMask() const noexcept {
|
2020-12-30 06:25:23 +01:00
|
|
|
return aspect_mask;
|
|
|
|
}
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-02-13 22:08:50 +01:00
|
|
|
[[nodiscard]] VkImageView StorageImageView(s32 level) const noexcept {
|
|
|
|
return *storage_image_views[level];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true when the image is already initialized and mark it as initialized
|
|
|
|
[[nodiscard]] bool ExchangeInitialization() noexcept {
|
|
|
|
return std::exchange(initialized, true);
|
2021-02-13 22:49:24 +01:00
|
|
|
}
|
|
|
|
|
2021-07-19 04:32:03 +02:00
|
|
|
bool ScaleUp(bool save_as_backup = false);
|
2021-07-18 18:40:14 +02:00
|
|
|
|
2021-07-19 04:32:03 +02:00
|
|
|
bool ScaleDown(bool save_as_backup = false);
|
|
|
|
|
|
|
|
void SwapBackup();
|
2021-07-18 18:40:14 +02:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
private:
|
|
|
|
VKScheduler* scheduler;
|
|
|
|
vk::Image image;
|
2020-12-31 02:58:05 +01:00
|
|
|
MemoryCommit commit;
|
2021-02-13 22:49:24 +01:00
|
|
|
vk::ImageView image_view;
|
2021-02-13 22:08:50 +01:00
|
|
|
std::vector<vk::ImageView> storage_image_views;
|
2020-12-30 06:25:23 +01:00
|
|
|
VkImageAspectFlags aspect_mask = 0;
|
|
|
|
bool initialized = false;
|
2021-07-18 18:40:14 +02:00
|
|
|
TextureCacheRuntime* runtime;
|
|
|
|
u32 scaling_count{};
|
2021-07-19 04:32:03 +02:00
|
|
|
vk::Image backup_image{};
|
|
|
|
MemoryCommit backup_commit{};
|
|
|
|
bool has_backup{};
|
2020-01-14 00:36:03 +01:00
|
|
|
};
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
class ImageView : public VideoCommon::ImageViewBase {
|
2020-01-14 00:36:03 +01:00
|
|
|
public:
|
2020-12-30 06:25:23 +01:00
|
|
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
|
2021-04-07 01:14:55 +02:00
|
|
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
|
|
|
|
const VideoCommon::ImageViewInfo&, GPUVAddr);
|
2021-07-28 07:47:06 +02:00
|
|
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkImageView DepthView();
|
2020-05-30 04:32:41 +02:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkImageView StencilView();
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2021-04-09 06:45:39 +02:00
|
|
|
[[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type,
|
|
|
|
Shader::ImageFormat image_format);
|
|
|
|
|
|
|
|
[[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept {
|
|
|
|
return *image_views[static_cast<size_t>(texture_type)];
|
2020-01-16 22:23:10 +01:00
|
|
|
}
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkImage ImageHandle() const noexcept {
|
|
|
|
return image_handle;
|
2020-01-14 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkImageView RenderTarget() const noexcept {
|
|
|
|
return render_target;
|
2020-02-16 08:12:38 +01:00
|
|
|
}
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkSampleCountFlagBits Samples() const noexcept {
|
|
|
|
return samples;
|
2020-01-14 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
2021-04-07 01:14:55 +02:00
|
|
|
[[nodiscard]] GPUVAddr GpuAddr() const noexcept {
|
|
|
|
return gpu_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] u32 BufferSize() const noexcept {
|
|
|
|
return buffer_size;
|
|
|
|
}
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
private:
|
2021-04-09 06:45:39 +02:00
|
|
|
struct StorageViews {
|
|
|
|
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> signeds;
|
|
|
|
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> unsigneds;
|
|
|
|
};
|
|
|
|
|
|
|
|
[[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-26 05:10:53 +01:00
|
|
|
const Device* device = nullptr;
|
2021-04-09 06:45:39 +02:00
|
|
|
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
|
|
|
|
std::unique_ptr<StorageViews> storage_views;
|
2020-12-30 06:25:23 +01:00
|
|
|
vk::ImageView depth_view;
|
|
|
|
vk::ImageView stencil_view;
|
|
|
|
VkImage image_handle = VK_NULL_HANDLE;
|
|
|
|
VkImageView render_target = VK_NULL_HANDLE;
|
|
|
|
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
2021-04-07 01:14:55 +02:00
|
|
|
GPUVAddr gpu_addr = 0;
|
|
|
|
u32 buffer_size = 0;
|
2020-12-30 06:25:23 +01:00
|
|
|
};
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
class ImageAlloc : public VideoCommon::ImageAllocBase {};
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
class Sampler {
|
|
|
|
public:
|
|
|
|
explicit Sampler(TextureCacheRuntime&, const Tegra::Texture::TSCEntry&);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkSampler Handle() const noexcept {
|
|
|
|
return *sampler;
|
2020-01-14 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2020-12-30 06:25:23 +01:00
|
|
|
vk::Sampler sampler;
|
2020-01-14 00:36:03 +01:00
|
|
|
};
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
class Framebuffer {
|
2020-01-14 00:36:03 +01:00
|
|
|
public:
|
2020-12-30 06:25:23 +01:00
|
|
|
explicit Framebuffer(TextureCacheRuntime&, std::span<ImageView*, NUM_RT> color_buffers,
|
|
|
|
ImageView* depth_buffer, const VideoCommon::RenderTargets& key);
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkFramebuffer Handle() const noexcept {
|
|
|
|
return *framebuffer;
|
|
|
|
}
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkRenderPass RenderPass() const noexcept {
|
|
|
|
return renderpass;
|
|
|
|
}
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkExtent2D RenderArea() const noexcept {
|
|
|
|
return render_area;
|
|
|
|
}
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] VkSampleCountFlagBits Samples() const noexcept {
|
|
|
|
return samples;
|
|
|
|
}
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] u32 NumColorBuffers() const noexcept {
|
|
|
|
return num_color_buffers;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] u32 NumImages() const noexcept {
|
|
|
|
return num_images;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] const std::array<VkImage, 9>& Images() const noexcept {
|
|
|
|
return images;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] const std::array<VkImageSubresourceRange, 9>& ImageRanges() const noexcept {
|
|
|
|
return image_ranges;
|
|
|
|
}
|
|
|
|
|
2021-08-15 05:19:01 +02:00
|
|
|
[[nodiscard]] bool HasAspectColorBit(size_t index) const noexcept {
|
|
|
|
return (image_ranges.at(index).aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] bool HasAspectDepthBit() const noexcept {
|
|
|
|
return has_depth;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] bool HasAspectStencilBit() const noexcept {
|
|
|
|
return has_stencil;
|
|
|
|
}
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
private:
|
|
|
|
vk::Framebuffer framebuffer;
|
|
|
|
VkRenderPass renderpass{};
|
|
|
|
VkExtent2D render_area{};
|
|
|
|
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
u32 num_color_buffers = 0;
|
|
|
|
u32 num_images = 0;
|
|
|
|
std::array<VkImage, 9> images{};
|
|
|
|
std::array<VkImageSubresourceRange, 9> image_ranges{};
|
2021-08-15 05:19:01 +02:00
|
|
|
bool has_depth{};
|
|
|
|
bool has_stencil{};
|
2020-12-30 06:25:23 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct TextureCacheParams {
|
|
|
|
static constexpr bool ENABLE_VALIDATION = true;
|
|
|
|
static constexpr bool FRAMEBUFFER_BLITS = false;
|
|
|
|
static constexpr bool HAS_EMULATED_COPIES = false;
|
2021-06-17 00:29:48 +02:00
|
|
|
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
2020-12-30 06:25:23 +01:00
|
|
|
|
|
|
|
using Runtime = Vulkan::TextureCacheRuntime;
|
|
|
|
using Image = Vulkan::Image;
|
|
|
|
using ImageAlloc = Vulkan::ImageAlloc;
|
|
|
|
using ImageView = Vulkan::ImageView;
|
|
|
|
using Sampler = Vulkan::Sampler;
|
|
|
|
using Framebuffer = Vulkan::Framebuffer;
|
2020-01-14 00:36:03 +01:00
|
|
|
};
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
using TextureCache = VideoCommon::TextureCache<TextureCacheParams>;
|
|
|
|
|
2020-01-14 00:36:03 +01:00
|
|
|
} // namespace Vulkan
|