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
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "video_core/renderer_vulkan/vk_image.h"
|
|
|
|
#include "video_core/renderer_vulkan/vk_memory_manager.h"
|
|
|
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
2020-03-27 05:33:21 +01:00
|
|
|
#include "video_core/renderer_vulkan/wrapper.h"
|
2020-01-14 00:36:03 +01:00
|
|
|
#include "video_core/texture_cache/surface_base.h"
|
|
|
|
#include "video_core/texture_cache/texture_cache.h"
|
|
|
|
|
|
|
|
namespace VideoCore {
|
|
|
|
class RasterizerInterface;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace Vulkan {
|
|
|
|
|
|
|
|
class RasterizerVulkan;
|
|
|
|
class VKDevice;
|
|
|
|
class VKScheduler;
|
|
|
|
class VKStagingBufferPool;
|
|
|
|
|
|
|
|
class CachedSurfaceView;
|
|
|
|
class CachedSurface;
|
|
|
|
|
|
|
|
using Surface = std::shared_ptr<CachedSurface>;
|
|
|
|
using View = std::shared_ptr<CachedSurfaceView>;
|
|
|
|
using TextureCacheBase = VideoCommon::TextureCache<Surface, View>;
|
|
|
|
|
|
|
|
using VideoCommon::SurfaceParams;
|
|
|
|
using VideoCommon::ViewParams;
|
|
|
|
|
|
|
|
class CachedSurface final : public VideoCommon::SurfaceBase<View> {
|
|
|
|
friend CachedSurfaceView;
|
|
|
|
|
|
|
|
public:
|
2020-12-05 10:51:14 +01:00
|
|
|
explicit CachedSurface(const VKDevice& device_, VKMemoryManager& memory_manager_,
|
|
|
|
VKScheduler& scheduler_, VKStagingBufferPool& staging_pool_,
|
|
|
|
GPUVAddr gpu_addr_, const SurfaceParams& params_);
|
2020-01-14 00:36:03 +01:00
|
|
|
~CachedSurface();
|
|
|
|
|
|
|
|
void UploadTexture(const std::vector<u8>& staging_buffer) override;
|
|
|
|
void DownloadTexture(std::vector<u8>& staging_buffer) override;
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
void FullTransition(VkPipelineStageFlags new_stage_mask, VkAccessFlags new_access,
|
|
|
|
VkImageLayout new_layout) {
|
2020-01-14 00:36:03 +01:00
|
|
|
image->Transition(0, static_cast<u32>(params.GetNumLayers()), 0, params.num_levels,
|
|
|
|
new_stage_mask, new_access, new_layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Transition(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels,
|
2020-03-27 05:33:21 +01:00
|
|
|
VkPipelineStageFlags new_stage_mask, VkAccessFlags new_access,
|
|
|
|
VkImageLayout new_layout) {
|
2020-01-14 00:36:03 +01:00
|
|
|
image->Transition(base_layer, num_layers, base_level, num_levels, new_stage_mask,
|
|
|
|
new_access, new_layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
VKImage& GetImage() {
|
|
|
|
return *image;
|
|
|
|
}
|
|
|
|
|
|
|
|
const VKImage& GetImage() const {
|
|
|
|
return *image;
|
|
|
|
}
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkImage GetImageHandle() const {
|
|
|
|
return *image->GetHandle();
|
2020-01-14 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkImageAspectFlags GetAspectMask() const {
|
2020-01-14 00:36:03 +01:00
|
|
|
return image->GetAspectMask();
|
|
|
|
}
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkBufferView GetBufferViewHandle() const {
|
2020-01-14 00:36:03 +01:00
|
|
|
return *buffer_view;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2020-11-15 19:20:17 +01:00
|
|
|
void DecorateSurfaceName() override;
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-12-05 10:51:14 +01:00
|
|
|
View CreateView(const ViewParams& view_params) override;
|
2020-01-14 00:36:03 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
void UploadBuffer(const std::vector<u8>& staging_buffer);
|
|
|
|
|
|
|
|
void UploadImage(const std::vector<u8>& staging_buffer);
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkBufferImageCopy GetBufferImageCopy(u32 level) const;
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkImageSubresourceRange GetImageSubresourceRange() const;
|
2020-01-14 00:36:03 +01:00
|
|
|
|
|
|
|
const VKDevice& device;
|
|
|
|
VKMemoryManager& memory_manager;
|
|
|
|
VKScheduler& scheduler;
|
|
|
|
VKStagingBufferPool& staging_pool;
|
|
|
|
|
|
|
|
std::optional<VKImage> image;
|
2020-03-27 05:33:21 +01:00
|
|
|
vk::Buffer buffer;
|
|
|
|
vk::BufferView buffer_view;
|
2020-01-14 00:36:03 +01:00
|
|
|
VKMemoryCommit commit;
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkFormat format = VK_FORMAT_UNDEFINED;
|
2020-01-14 00:36:03 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class CachedSurfaceView final : public VideoCommon::ViewBase {
|
|
|
|
public:
|
2020-12-05 10:51:14 +01:00
|
|
|
explicit CachedSurfaceView(const VKDevice& device_, CachedSurface& surface_,
|
|
|
|
const ViewParams& view_params_);
|
2020-01-14 00:36:03 +01:00
|
|
|
~CachedSurfaceView();
|
|
|
|
|
2020-05-30 04:32:41 +02:00
|
|
|
VkImageView GetImageView(Tegra::Texture::SwizzleSource x_source,
|
|
|
|
Tegra::Texture::SwizzleSource y_source,
|
|
|
|
Tegra::Texture::SwizzleSource z_source,
|
|
|
|
Tegra::Texture::SwizzleSource w_source);
|
|
|
|
|
|
|
|
VkImageView GetAttachment();
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-01-16 22:23:10 +01:00
|
|
|
bool IsSameSurface(const CachedSurfaceView& rhs) const {
|
|
|
|
return &surface == &rhs.surface;
|
|
|
|
}
|
2020-01-14 00:36:03 +01:00
|
|
|
|
|
|
|
u32 GetWidth() const {
|
2020-12-05 10:51:14 +01:00
|
|
|
return surface_params.GetMipWidth(base_level);
|
2020-01-14 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
u32 GetHeight() const {
|
2020-12-05 10:51:14 +01:00
|
|
|
return surface_params.GetMipHeight(base_level);
|
2020-01-14 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
2020-02-16 08:12:38 +01:00
|
|
|
u32 GetNumLayers() const {
|
|
|
|
return num_layers;
|
|
|
|
}
|
|
|
|
|
2020-01-14 00:36:03 +01:00
|
|
|
bool IsBufferView() const {
|
|
|
|
return buffer_view;
|
|
|
|
}
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkImage GetImage() const {
|
2020-01-14 00:36:03 +01:00
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkBufferView GetBufferView() const {
|
2020-01-14 00:36:03 +01:00
|
|
|
return buffer_view;
|
|
|
|
}
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkImageSubresourceRange GetImageSubresourceRange() const {
|
2020-01-14 00:36:03 +01:00
|
|
|
return {aspect_mask, base_level, num_levels, base_layer, num_layers};
|
|
|
|
}
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkImageSubresourceLayers GetImageSubresourceLayers() const {
|
2020-01-14 00:36:03 +01:00
|
|
|
return {surface.GetAspectMask(), base_level, base_layer, num_layers};
|
|
|
|
}
|
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
void Transition(VkImageLayout new_layout, VkPipelineStageFlags new_stage_mask,
|
|
|
|
VkAccessFlags new_access) const {
|
2020-01-14 00:36:03 +01:00
|
|
|
surface.Transition(base_layer, num_layers, base_level, num_levels, new_stage_mask,
|
|
|
|
new_access, new_layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MarkAsModified(u64 tick) {
|
|
|
|
surface.MarkAsModified(true, tick);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Store a copy of these values to avoid double dereference when reading them
|
2020-12-05 10:51:14 +01:00
|
|
|
const SurfaceParams surface_params;
|
2020-03-27 05:33:21 +01:00
|
|
|
const VkImage image;
|
|
|
|
const VkBufferView buffer_view;
|
|
|
|
const VkImageAspectFlags aspect_mask;
|
2020-01-14 00:36:03 +01:00
|
|
|
|
|
|
|
const VKDevice& device;
|
|
|
|
CachedSurface& surface;
|
|
|
|
const u32 base_level;
|
|
|
|
const u32 num_levels;
|
2020-03-27 05:33:21 +01:00
|
|
|
const VkImageViewType image_view_type;
|
2020-05-30 04:32:41 +02:00
|
|
|
u32 base_layer = 0;
|
|
|
|
u32 num_layers = 0;
|
|
|
|
u32 base_slice = 0;
|
|
|
|
u32 num_slices = 0;
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-03-27 05:33:21 +01:00
|
|
|
VkImageView last_image_view = nullptr;
|
|
|
|
u32 last_swizzle = 0;
|
2020-01-14 00:36:03 +01:00
|
|
|
|
2020-05-30 04:32:41 +02:00
|
|
|
vk::ImageView render_target;
|
2020-03-27 05:33:21 +01:00
|
|
|
std::unordered_map<u32, vk::ImageView> view_cache;
|
2020-01-14 00:36:03 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class VKTextureCache final : public TextureCacheBase {
|
|
|
|
public:
|
2020-12-05 17:40:14 +01:00
|
|
|
explicit VKTextureCache(VideoCore::RasterizerInterface& rasterizer_,
|
|
|
|
Tegra::Engines::Maxwell3D& maxwell3d_,
|
|
|
|
Tegra::MemoryManager& gpu_memory_, const VKDevice& device_,
|
|
|
|
VKMemoryManager& memory_manager_, VKScheduler& scheduler_,
|
|
|
|
VKStagingBufferPool& staging_pool_);
|
2020-01-14 00:36:03 +01:00
|
|
|
~VKTextureCache();
|
|
|
|
|
|
|
|
private:
|
|
|
|
Surface CreateSurface(GPUVAddr gpu_addr, const SurfaceParams& params) override;
|
|
|
|
|
|
|
|
void ImageCopy(Surface& src_surface, Surface& dst_surface,
|
|
|
|
const VideoCommon::CopyParams& copy_params) override;
|
|
|
|
|
|
|
|
void ImageBlit(View& src_view, View& dst_view,
|
|
|
|
const Tegra::Engines::Fermi2D::Config& copy_config) override;
|
|
|
|
|
|
|
|
void BufferCopy(Surface& src_surface, Surface& dst_surface) override;
|
|
|
|
|
|
|
|
const VKDevice& device;
|
|
|
|
VKMemoryManager& memory_manager;
|
|
|
|
VKScheduler& scheduler;
|
|
|
|
VKStagingBufferPool& staging_pool;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Vulkan
|