299 lines
9.3 KiB
C++
299 lines
9.3 KiB
C++
|
// Copyright 2023 Citra Emulator Project
|
||
|
// Licensed under GPLv2 or any later version
|
||
|
// Refer to the license.txt file included.
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <deque>
|
||
|
#include <span>
|
||
|
#include "video_core/rasterizer_cache/framebuffer_base.h"
|
||
|
#include "video_core/rasterizer_cache/rasterizer_cache_base.h"
|
||
|
#include "video_core/rasterizer_cache/surface_base.h"
|
||
|
#include "video_core/renderer_vulkan/vk_blit_helper.h"
|
||
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||
|
#include "video_core/renderer_vulkan/vk_stream_buffer.h"
|
||
|
|
||
|
VK_DEFINE_HANDLE(VmaAllocation)
|
||
|
|
||
|
namespace VideoCore {
|
||
|
struct Material;
|
||
|
}
|
||
|
|
||
|
namespace Vulkan {
|
||
|
|
||
|
class Instance;
|
||
|
class RenderpassCache;
|
||
|
class DescriptorPool;
|
||
|
class DescriptorSetProvider;
|
||
|
class Surface;
|
||
|
|
||
|
struct Handle {
|
||
|
VmaAllocation alloc;
|
||
|
vk::Image image;
|
||
|
vk::UniqueImageView image_view;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Provides texture manipulation functions to the rasterizer cache
|
||
|
* Separating this into a class makes it easier to abstract graphics API code
|
||
|
*/
|
||
|
class TextureRuntime {
|
||
|
friend class Surface;
|
||
|
|
||
|
public:
|
||
|
explicit TextureRuntime(const Instance& instance, Scheduler& scheduler,
|
||
|
RenderpassCache& renderpass_cache, DescriptorPool& pool,
|
||
|
DescriptorSetProvider& texture_provider, u32 num_swapchain_images);
|
||
|
~TextureRuntime();
|
||
|
|
||
|
const Instance& GetInstance() const {
|
||
|
return instance;
|
||
|
}
|
||
|
|
||
|
Scheduler& GetScheduler() const {
|
||
|
return scheduler;
|
||
|
}
|
||
|
|
||
|
RenderpassCache& GetRenderpassCache() {
|
||
|
return renderpass_cache;
|
||
|
}
|
||
|
|
||
|
/// Returns the removal threshold ticks for the garbage collector
|
||
|
u32 RemoveThreshold();
|
||
|
|
||
|
/// Submits and waits for current GPU work.
|
||
|
void Finish();
|
||
|
|
||
|
/// Maps an internal staging buffer of the provided size for pixel uploads/downloads
|
||
|
VideoCore::StagingData FindStaging(u32 size, bool upload);
|
||
|
|
||
|
/// Attempts to reinterpret a rectangle of source to another rectangle of dest
|
||
|
bool Reinterpret(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
|
||
|
|
||
|
/// Fills the rectangle of the texture with the clear value provided
|
||
|
bool ClearTexture(Surface& surface, const VideoCore::TextureClear& clear);
|
||
|
|
||
|
/// Copies a rectangle of src_tex to another rectange of dst_rect
|
||
|
bool CopyTextures(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
|
||
|
|
||
|
/// Blits a rectangle of src_tex to another rectange of dst_rect
|
||
|
bool BlitTextures(Surface& surface, Surface& dest, const VideoCore::TextureBlit& blit);
|
||
|
|
||
|
/// Generates mipmaps for all the available levels of the texture
|
||
|
void GenerateMipmaps(Surface& surface);
|
||
|
|
||
|
/// Returns true if the provided pixel format needs convertion
|
||
|
bool NeedsConversion(VideoCore::PixelFormat format) const;
|
||
|
|
||
|
/// Removes any descriptor sets that contain the provided image view.
|
||
|
void FreeDescriptorSetsWithImage(vk::ImageView image_view);
|
||
|
|
||
|
private:
|
||
|
/// Clears a partial texture rect using a clear rectangle
|
||
|
void ClearTextureWithRenderpass(Surface& surface, const VideoCore::TextureClear& clear);
|
||
|
|
||
|
private:
|
||
|
const Instance& instance;
|
||
|
Scheduler& scheduler;
|
||
|
RenderpassCache& renderpass_cache;
|
||
|
DescriptorSetProvider& texture_provider;
|
||
|
BlitHelper blit_helper;
|
||
|
StreamBuffer upload_buffer;
|
||
|
StreamBuffer download_buffer;
|
||
|
u32 num_swapchain_images;
|
||
|
};
|
||
|
|
||
|
class Surface : public VideoCore::SurfaceBase {
|
||
|
friend class TextureRuntime;
|
||
|
|
||
|
public:
|
||
|
explicit Surface(TextureRuntime& runtime, const VideoCore::SurfaceParams& params);
|
||
|
explicit Surface(TextureRuntime& runtime, const VideoCore::SurfaceBase& surface,
|
||
|
const VideoCore::Material* materal);
|
||
|
~Surface();
|
||
|
|
||
|
Surface(const Surface&) = delete;
|
||
|
Surface& operator=(const Surface&) = delete;
|
||
|
|
||
|
Surface(Surface&& o) noexcept = default;
|
||
|
Surface& operator=(Surface&& o) noexcept = default;
|
||
|
|
||
|
vk::ImageAspectFlags Aspect() const noexcept {
|
||
|
return traits.aspect;
|
||
|
}
|
||
|
|
||
|
/// Returns the image at index, otherwise the base image
|
||
|
vk::Image Image(u32 index = 1) const noexcept;
|
||
|
|
||
|
/// Returns the image view at index, otherwise the base view
|
||
|
vk::ImageView ImageView(u32 index = 1) const noexcept;
|
||
|
|
||
|
/// Returns a copy of the upscaled image handle, used for feedback loops.
|
||
|
vk::ImageView CopyImageView() noexcept;
|
||
|
|
||
|
/// Returns the framebuffer view of the surface image
|
||
|
vk::ImageView FramebufferView() noexcept;
|
||
|
|
||
|
/// Returns the depth view of the surface image
|
||
|
vk::ImageView DepthView() noexcept;
|
||
|
|
||
|
/// Returns the stencil view of the surface image
|
||
|
vk::ImageView StencilView() noexcept;
|
||
|
|
||
|
/// Returns the R32 image view used for atomic load/store
|
||
|
vk::ImageView StorageView() noexcept;
|
||
|
|
||
|
/// Returns a framebuffer handle for rendering to this surface
|
||
|
vk::Framebuffer Framebuffer() noexcept;
|
||
|
|
||
|
/// Uploads pixel data in staging to a rectangle region of the surface texture
|
||
|
void Upload(const VideoCore::BufferTextureCopy& upload, const VideoCore::StagingData& staging);
|
||
|
|
||
|
/// Uploads the custom material to the surface allocation.
|
||
|
void UploadCustom(const VideoCore::Material* material, u32 level);
|
||
|
|
||
|
/// Downloads pixel data to staging from a rectangle region of the surface texture
|
||
|
void Download(const VideoCore::BufferTextureCopy& download,
|
||
|
const VideoCore::StagingData& staging);
|
||
|
|
||
|
/// Scales up the surface to match the new resolution scale.
|
||
|
void ScaleUp(u32 new_scale);
|
||
|
|
||
|
/// Returns the bpp of the internal surface format
|
||
|
u32 GetInternalBytesPerPixel() const;
|
||
|
|
||
|
/// Returns the access flags indicative of the surface
|
||
|
vk::AccessFlags AccessFlags() const noexcept;
|
||
|
|
||
|
/// Returns the pipeline stage flags indicative of the surface
|
||
|
vk::PipelineStageFlags PipelineStageFlags() const noexcept;
|
||
|
|
||
|
private:
|
||
|
/// Performs blit between the scaled/unscaled images
|
||
|
void BlitScale(const VideoCore::TextureBlit& blit, bool up_scale);
|
||
|
|
||
|
/// Downloads scaled depth stencil data
|
||
|
void DepthStencilDownload(const VideoCore::BufferTextureCopy& download,
|
||
|
const VideoCore::StagingData& staging);
|
||
|
|
||
|
public:
|
||
|
TextureRuntime* runtime;
|
||
|
const Instance* instance;
|
||
|
Scheduler* scheduler;
|
||
|
FormatTraits traits;
|
||
|
std::array<Handle, 3> handles{};
|
||
|
std::array<vk::UniqueFramebuffer, 2> framebuffers{};
|
||
|
Handle copy_handle;
|
||
|
vk::UniqueImageView depth_view;
|
||
|
vk::UniqueImageView stencil_view;
|
||
|
vk::UniqueImageView storage_view;
|
||
|
bool is_framebuffer{};
|
||
|
bool is_storage{};
|
||
|
};
|
||
|
|
||
|
class Framebuffer : public VideoCore::FramebufferParams {
|
||
|
public:
|
||
|
explicit Framebuffer(TextureRuntime& runtime, const VideoCore::FramebufferParams& params,
|
||
|
Surface* color, Surface* depth_stencil);
|
||
|
~Framebuffer();
|
||
|
|
||
|
Framebuffer(const Framebuffer&) = delete;
|
||
|
Framebuffer& operator=(const Framebuffer&) = delete;
|
||
|
|
||
|
Framebuffer(Framebuffer&& o) noexcept = default;
|
||
|
Framebuffer& operator=(Framebuffer&& o) noexcept = default;
|
||
|
|
||
|
VideoCore::PixelFormat Format(VideoCore::SurfaceType type) const noexcept {
|
||
|
return formats[Index(type)];
|
||
|
}
|
||
|
|
||
|
[[nodiscard]] vk::ImageView ImageView(VideoCore::SurfaceType type) const noexcept {
|
||
|
return image_views[Index(type)];
|
||
|
}
|
||
|
|
||
|
[[nodiscard]] vk::Framebuffer Handle() const noexcept {
|
||
|
return framebuffer.get();
|
||
|
}
|
||
|
|
||
|
[[nodiscard]] std::array<vk::Image, 2> Images() const noexcept {
|
||
|
return images;
|
||
|
}
|
||
|
|
||
|
[[nodiscard]] std::array<vk::ImageAspectFlags, 2> Aspects() const noexcept {
|
||
|
return aspects;
|
||
|
}
|
||
|
|
||
|
[[nodiscard]] vk::RenderPass RenderPass() const noexcept {
|
||
|
return render_pass;
|
||
|
}
|
||
|
|
||
|
u32 Scale() const noexcept {
|
||
|
return res_scale;
|
||
|
}
|
||
|
|
||
|
u32 Width() const noexcept {
|
||
|
return width;
|
||
|
}
|
||
|
|
||
|
u32 Height() const noexcept {
|
||
|
return height;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
std::array<vk::Image, 2> images{};
|
||
|
std::array<vk::ImageView, 2> image_views{};
|
||
|
vk::UniqueFramebuffer framebuffer;
|
||
|
vk::RenderPass render_pass;
|
||
|
std::array<vk::ImageAspectFlags, 2> aspects{};
|
||
|
std::array<VideoCore::PixelFormat, 2> formats{VideoCore::PixelFormat::Invalid,
|
||
|
VideoCore::PixelFormat::Invalid};
|
||
|
u32 width{};
|
||
|
u32 height{};
|
||
|
u32 res_scale{1};
|
||
|
};
|
||
|
|
||
|
class Sampler {
|
||
|
public:
|
||
|
Sampler(TextureRuntime& runtime, const VideoCore::SamplerParams& params);
|
||
|
~Sampler();
|
||
|
|
||
|
Sampler(const Sampler&) = delete;
|
||
|
Sampler& operator=(const Sampler&) = delete;
|
||
|
|
||
|
Sampler(Sampler&& o) noexcept = default;
|
||
|
Sampler& operator=(Sampler&& o) noexcept = default;
|
||
|
|
||
|
[[nodiscard]] vk::Sampler Handle() const noexcept {
|
||
|
return sampler.get();
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
vk::UniqueSampler sampler;
|
||
|
};
|
||
|
|
||
|
class DebugScope {
|
||
|
public:
|
||
|
template <typename... T>
|
||
|
explicit DebugScope(TextureRuntime& runtime, Common::Vec4f color,
|
||
|
fmt::format_string<T...> format, T... args)
|
||
|
: DebugScope{runtime, color, fmt::format(format, std::forward<T>(args)...)} {}
|
||
|
explicit DebugScope(TextureRuntime& runtime, Common::Vec4f color, std::string_view label);
|
||
|
~DebugScope();
|
||
|
|
||
|
private:
|
||
|
Scheduler& scheduler;
|
||
|
bool has_debug_tool;
|
||
|
};
|
||
|
|
||
|
struct Traits {
|
||
|
using Runtime = Vulkan::TextureRuntime;
|
||
|
using Surface = Vulkan::Surface;
|
||
|
using Sampler = Vulkan::Sampler;
|
||
|
using Framebuffer = Vulkan::Framebuffer;
|
||
|
using DebugScope = Vulkan::DebugScope;
|
||
|
};
|
||
|
|
||
|
using RasterizerCache = VideoCore::RasterizerCache<Traits>;
|
||
|
|
||
|
} // namespace Vulkan
|