video_core: Move rasterizer cache template definitions to separate file
* Helps with build times
This commit is contained in:
@ -33,6 +33,7 @@ add_library(video_core STATIC
|
||||
rasterizer_cache/pixel_format.h
|
||||
rasterizer_cache/rasterizer_cache.cpp
|
||||
rasterizer_cache/rasterizer_cache.h
|
||||
rasterizer_cache/rasterizer_cache_base.h
|
||||
rasterizer_cache/surface_base.h
|
||||
rasterizer_cache/utils.cpp
|
||||
rasterizer_cache/utils.h
|
||||
@ -46,6 +47,7 @@ add_library(video_core STATIC
|
||||
renderer_opengl/gl_format_reinterpreter.h
|
||||
renderer_opengl/gl_rasterizer.cpp
|
||||
renderer_opengl/gl_rasterizer.h
|
||||
renderer_opengl/gl_rasterizer_cache.cpp
|
||||
renderer_opengl/gl_resource_manager.cpp
|
||||
renderer_opengl/gl_resource_manager.h
|
||||
renderer_opengl/gl_shader_decompiler.cpp
|
||||
@ -99,6 +101,7 @@ add_library(video_core STATIC
|
||||
renderer_vulkan/vk_master_semaphore.h
|
||||
renderer_vulkan/vk_rasterizer.cpp
|
||||
renderer_vulkan/vk_rasterizer.h
|
||||
renderer_vulkan/vk_rasterizer_cache.cpp
|
||||
renderer_vulkan/vk_scheduler.cpp
|
||||
renderer_vulkan/vk_scheduler.h
|
||||
renderer_vulkan/vk_resource_pool.cpp
|
||||
|
@ -4,179 +4,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include "common/alignment.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "core/memory.h"
|
||||
#include "video_core/pica_state.h"
|
||||
#include "video_core/rasterizer_cache/surface_base.h"
|
||||
#include "video_core/rasterizer_cache/surface_params.h"
|
||||
#include "video_core/rasterizer_cache/utils.h"
|
||||
#include "video_core/texture/texture_decode.h"
|
||||
#include "video_core/rasterizer_cache/rasterizer_cache_base.h"
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
inline auto RangeFromInterval(auto& map, const auto& interval) {
|
||||
return boost::make_iterator_range(map.equal_range(interval));
|
||||
}
|
||||
|
||||
enum class ScaleMatch {
|
||||
Exact, ///< Only accept same res scale
|
||||
Upscale, ///< Only allow higher scale than params
|
||||
Ignore ///< Accept every scaled res
|
||||
};
|
||||
|
||||
enum class MatchFlags {
|
||||
Invalid = 1, ///< Surface is allowed to be only partially valid
|
||||
Exact = 1 << 1, ///< Surface perfectly matches params
|
||||
SubRect = 1 << 2, ///< Surface encompasses params
|
||||
Copy = 1 << 3, ///< Surface that can be used as a copy source
|
||||
Expand = 1 << 4, ///< Surface that can expand params
|
||||
TexCopy = 1 << 5 ///< Surface that will match a display transfer "texture copy" parameters
|
||||
};
|
||||
|
||||
DECLARE_ENUM_FLAG_OPERATORS(MatchFlags);
|
||||
|
||||
class RasterizerAccelerated;
|
||||
|
||||
template <class T>
|
||||
class RasterizerCache : NonCopyable {
|
||||
public:
|
||||
using TextureRuntime = typename T::RuntimeType;
|
||||
using Surface = std::shared_ptr<typename T::SurfaceType>;
|
||||
using Watcher = SurfaceWatcher<typename T::SurfaceType>;
|
||||
|
||||
private:
|
||||
/// Declare rasterizer interval types
|
||||
using SurfaceSet = std::set<Surface>;
|
||||
using SurfaceMap = boost::icl::interval_map<PAddr, Surface, boost::icl::partial_absorber,
|
||||
std::less, boost::icl::inplace_plus,
|
||||
boost::icl::inter_section, SurfaceInterval>;
|
||||
using SurfaceCache = boost::icl::interval_map<PAddr, SurfaceSet, boost::icl::partial_absorber,
|
||||
std::less, boost::icl::inplace_plus,
|
||||
boost::icl::inter_section, SurfaceInterval>;
|
||||
|
||||
static_assert(
|
||||
std::is_same<SurfaceRegions::interval_type, typename SurfaceCache::interval_type>() &&
|
||||
std::is_same<typename SurfaceMap::interval_type,
|
||||
typename SurfaceCache::interval_type>(),
|
||||
"Incorrect interval types");
|
||||
|
||||
using SurfaceRect_Tuple = std::tuple<Surface, Common::Rectangle<u32>>;
|
||||
using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, Common::Rectangle<u32>>;
|
||||
using PageMap = boost::icl::interval_map<u32, int>;
|
||||
|
||||
public:
|
||||
RasterizerCache(Memory::MemorySystem& memory, TextureRuntime& runtime);
|
||||
~RasterizerCache() = default;
|
||||
|
||||
/// Get the best surface match (and its match type) for the given flags
|
||||
template <MatchFlags find_flags>
|
||||
Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params,
|
||||
ScaleMatch match_scale_type,
|
||||
std::optional<SurfaceInterval> validate_interval = std::nullopt);
|
||||
|
||||
/// Blit one surface's texture to another
|
||||
bool BlitSurfaces(const Surface& src_surface, Common::Rectangle<u32> src_rect,
|
||||
const Surface& dst_surface, Common::Rectangle<u32> dst_rect);
|
||||
|
||||
/// Copy one surface's region to another
|
||||
void CopySurface(const Surface& src_surface, const Surface& dst_surface,
|
||||
SurfaceInterval copy_interval);
|
||||
|
||||
/// Load a texture from 3DS memory to OpenGL and cache it (if not already cached)
|
||||
Surface GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale,
|
||||
bool load_if_create);
|
||||
|
||||
/// Attempt to find a subrect (resolution scaled) of a surface, otherwise loads a texture from
|
||||
/// 3DS memory to OpenGL and caches it (if not already cached)
|
||||
SurfaceRect_Tuple GetSurfaceSubRect(const SurfaceParams& params, ScaleMatch match_res_scale,
|
||||
bool load_if_create);
|
||||
|
||||
/// Get a surface based on the texture configuration
|
||||
Surface GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config);
|
||||
Surface GetTextureSurface(const Pica::Texture::TextureInfo& info, u32 max_level = 0);
|
||||
|
||||
/// Get a texture cube based on the texture configuration
|
||||
const Surface& GetTextureCube(const TextureCubeConfig& config);
|
||||
|
||||
/// Get the color and depth surfaces based on the framebuffer configuration
|
||||
SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
|
||||
const Common::Rectangle<s32>& viewport_rect);
|
||||
|
||||
/// Get a surface that matches the fill config
|
||||
Surface GetFillSurface(const GPU::Regs::MemoryFillConfig& config);
|
||||
|
||||
/// Get a surface that matches a "texture copy" display transfer config
|
||||
SurfaceRect_Tuple GetTexCopySurface(const SurfaceParams& params);
|
||||
|
||||
/// Write any cached resources overlapping the region back to memory (if dirty)
|
||||
void FlushRegion(PAddr addr, u32 size, Surface flush_surface = nullptr);
|
||||
|
||||
/// Mark region as being invalidated by region_owner (nullptr if 3DS memory)
|
||||
void InvalidateRegion(PAddr addr, u32 size, const Surface& region_owner);
|
||||
|
||||
/// Flush all cached resources tracked by this cache manager
|
||||
void FlushAll();
|
||||
|
||||
/// Clear all cached resources tracked by this cache manager
|
||||
void ClearAll(bool flush);
|
||||
|
||||
private:
|
||||
void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface);
|
||||
|
||||
/// Update surface's texture for given region when necessary
|
||||
void ValidateSurface(const Surface& surface, PAddr addr, u32 size);
|
||||
|
||||
/// Copies pixel data in interval from the guest VRAM to the host GPU surface
|
||||
void UploadSurface(const Surface& surface, SurfaceInterval interval);
|
||||
|
||||
/// Copies pixel data in interval from the host GPU surface to the guest VRAM
|
||||
void DownloadSurface(const Surface& surface, SurfaceInterval interval);
|
||||
|
||||
/// Downloads a fill surface to guest VRAM
|
||||
void DownloadFillSurface(const Surface& surface, SurfaceInterval interval);
|
||||
|
||||
/// Returns false if there is a surface in the cache at the interval with the same bit-width,
|
||||
bool NoUnimplementedReinterpretations(const Surface& surface, SurfaceParams& params,
|
||||
SurfaceInterval interval);
|
||||
|
||||
/// Return true if a surface with an invalid pixel format exists at the interval
|
||||
bool IntervalHasInvalidPixelFormat(SurfaceParams& params, SurfaceInterval interval);
|
||||
|
||||
/// Attempt to find a reinterpretable surface in the cache and use it to copy for validation
|
||||
bool ValidateByReinterpretation(const Surface& surface, SurfaceParams& params,
|
||||
SurfaceInterval interval);
|
||||
|
||||
/// Create a new surface
|
||||
Surface CreateSurface(SurfaceParams& params);
|
||||
|
||||
/// Register surface into the cache
|
||||
void RegisterSurface(const Surface& surface);
|
||||
|
||||
/// Remove surface from the cache
|
||||
void UnregisterSurface(const Surface& surface);
|
||||
|
||||
/// Increase/decrease the number of surface in pages touching the specified region
|
||||
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta);
|
||||
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
TextureRuntime& runtime;
|
||||
SurfaceCache surface_cache;
|
||||
PageMap cached_pages;
|
||||
SurfaceMap dirty_regions;
|
||||
SurfaceSet remove_surfaces;
|
||||
u16 resolution_scale_factor;
|
||||
std::unordered_map<TextureCubeConfig, Surface> texture_cube_cache;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
RasterizerCache<T>::RasterizerCache(Memory::MemorySystem& memory_, TextureRuntime& runtime_)
|
||||
: memory{memory_}, runtime{runtime_}, resolution_scale_factor{
|
||||
|
177
src/video_core/rasterizer_cache/rasterizer_cache_base.h
Normal file
177
src/video_core/rasterizer_cache/rasterizer_cache_base.h
Normal file
@ -0,0 +1,177 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include "video_core/rasterizer_cache/surface_base.h"
|
||||
#include "video_core/rasterizer_cache/surface_params.h"
|
||||
#include "video_core/rasterizer_cache/utils.h"
|
||||
#include "video_core/texture/texture_decode.h"
|
||||
|
||||
namespace Memory {
|
||||
class MemorySystem;
|
||||
}
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
inline auto RangeFromInterval(auto& map, const auto& interval) {
|
||||
return boost::make_iterator_range(map.equal_range(interval));
|
||||
}
|
||||
|
||||
enum class ScaleMatch {
|
||||
Exact, ///< Only accept same res scale
|
||||
Upscale, ///< Only allow higher scale than params
|
||||
Ignore ///< Accept every scaled res
|
||||
};
|
||||
|
||||
enum class MatchFlags {
|
||||
Invalid = 1, ///< Surface is allowed to be only partially valid
|
||||
Exact = 1 << 1, ///< Surface perfectly matches params
|
||||
SubRect = 1 << 2, ///< Surface encompasses params
|
||||
Copy = 1 << 3, ///< Surface that can be used as a copy source
|
||||
Expand = 1 << 4, ///< Surface that can expand params
|
||||
TexCopy = 1 << 5 ///< Surface that will match a display transfer "texture copy" parameters
|
||||
};
|
||||
|
||||
DECLARE_ENUM_FLAG_OPERATORS(MatchFlags);
|
||||
|
||||
class RasterizerAccelerated;
|
||||
|
||||
template <class T>
|
||||
class RasterizerCache : NonCopyable {
|
||||
public:
|
||||
using TextureRuntime = typename T::RuntimeType;
|
||||
using Surface = std::shared_ptr<typename T::SurfaceType>;
|
||||
using Watcher = SurfaceWatcher<typename T::SurfaceType>;
|
||||
|
||||
private:
|
||||
/// Declare rasterizer interval types
|
||||
using SurfaceSet = std::set<Surface>;
|
||||
using SurfaceMap = boost::icl::interval_map<PAddr, Surface, boost::icl::partial_absorber,
|
||||
std::less, boost::icl::inplace_plus,
|
||||
boost::icl::inter_section, SurfaceInterval>;
|
||||
using SurfaceCache = boost::icl::interval_map<PAddr, SurfaceSet, boost::icl::partial_absorber,
|
||||
std::less, boost::icl::inplace_plus,
|
||||
boost::icl::inter_section, SurfaceInterval>;
|
||||
|
||||
static_assert(
|
||||
std::is_same<SurfaceRegions::interval_type, typename SurfaceCache::interval_type>() &&
|
||||
std::is_same<typename SurfaceMap::interval_type,
|
||||
typename SurfaceCache::interval_type>(),
|
||||
"Incorrect interval types");
|
||||
|
||||
using SurfaceRect_Tuple = std::tuple<Surface, Common::Rectangle<u32>>;
|
||||
using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, Common::Rectangle<u32>>;
|
||||
using PageMap = boost::icl::interval_map<u32, int>;
|
||||
|
||||
public:
|
||||
RasterizerCache(Memory::MemorySystem& memory, TextureRuntime& runtime);
|
||||
~RasterizerCache() = default;
|
||||
|
||||
/// Get the best surface match (and its match type) for the given flags
|
||||
template <MatchFlags find_flags>
|
||||
Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params,
|
||||
ScaleMatch match_scale_type,
|
||||
std::optional<SurfaceInterval> validate_interval = std::nullopt);
|
||||
|
||||
/// Blit one surface's texture to another
|
||||
bool BlitSurfaces(const Surface& src_surface, Common::Rectangle<u32> src_rect,
|
||||
const Surface& dst_surface, Common::Rectangle<u32> dst_rect);
|
||||
|
||||
/// Copy one surface's region to another
|
||||
void CopySurface(const Surface& src_surface, const Surface& dst_surface,
|
||||
SurfaceInterval copy_interval);
|
||||
|
||||
/// Load a texture from 3DS memory to OpenGL and cache it (if not already cached)
|
||||
Surface GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale,
|
||||
bool load_if_create);
|
||||
|
||||
/// Attempt to find a subrect (resolution scaled) of a surface, otherwise loads a texture from
|
||||
/// 3DS memory to OpenGL and caches it (if not already cached)
|
||||
SurfaceRect_Tuple GetSurfaceSubRect(const SurfaceParams& params, ScaleMatch match_res_scale,
|
||||
bool load_if_create);
|
||||
|
||||
/// Get a surface based on the texture configuration
|
||||
Surface GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config);
|
||||
Surface GetTextureSurface(const Pica::Texture::TextureInfo& info, u32 max_level = 0);
|
||||
|
||||
/// Get a texture cube based on the texture configuration
|
||||
const Surface& GetTextureCube(const TextureCubeConfig& config);
|
||||
|
||||
/// Get the color and depth surfaces based on the framebuffer configuration
|
||||
SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
|
||||
const Common::Rectangle<s32>& viewport_rect);
|
||||
|
||||
/// Get a surface that matches the fill config
|
||||
Surface GetFillSurface(const GPU::Regs::MemoryFillConfig& config);
|
||||
|
||||
/// Get a surface that matches a "texture copy" display transfer config
|
||||
SurfaceRect_Tuple GetTexCopySurface(const SurfaceParams& params);
|
||||
|
||||
/// Write any cached resources overlapping the region back to memory (if dirty)
|
||||
void FlushRegion(PAddr addr, u32 size, Surface flush_surface = nullptr);
|
||||
|
||||
/// Mark region as being invalidated by region_owner (nullptr if 3DS memory)
|
||||
void InvalidateRegion(PAddr addr, u32 size, const Surface& region_owner);
|
||||
|
||||
/// Flush all cached resources tracked by this cache manager
|
||||
void FlushAll();
|
||||
|
||||
/// Clear all cached resources tracked by this cache manager
|
||||
void ClearAll(bool flush);
|
||||
|
||||
private:
|
||||
void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface);
|
||||
|
||||
/// Update surface's texture for given region when necessary
|
||||
void ValidateSurface(const Surface& surface, PAddr addr, u32 size);
|
||||
|
||||
/// Copies pixel data in interval from the guest VRAM to the host GPU surface
|
||||
void UploadSurface(const Surface& surface, SurfaceInterval interval);
|
||||
|
||||
/// Copies pixel data in interval from the host GPU surface to the guest VRAM
|
||||
void DownloadSurface(const Surface& surface, SurfaceInterval interval);
|
||||
|
||||
/// Downloads a fill surface to guest VRAM
|
||||
void DownloadFillSurface(const Surface& surface, SurfaceInterval interval);
|
||||
|
||||
/// Returns false if there is a surface in the cache at the interval with the same bit-width,
|
||||
bool NoUnimplementedReinterpretations(const Surface& surface, SurfaceParams& params,
|
||||
SurfaceInterval interval);
|
||||
|
||||
/// Return true if a surface with an invalid pixel format exists at the interval
|
||||
bool IntervalHasInvalidPixelFormat(SurfaceParams& params, SurfaceInterval interval);
|
||||
|
||||
/// Attempt to find a reinterpretable surface in the cache and use it to copy for validation
|
||||
bool ValidateByReinterpretation(const Surface& surface, SurfaceParams& params,
|
||||
SurfaceInterval interval);
|
||||
|
||||
/// Create a new surface
|
||||
Surface CreateSurface(SurfaceParams& params);
|
||||
|
||||
/// Register surface into the cache
|
||||
void RegisterSurface(const Surface& surface);
|
||||
|
||||
/// Remove surface from the cache
|
||||
void UnregisterSurface(const Surface& surface);
|
||||
|
||||
/// Increase/decrease the number of surface in pages touching the specified region
|
||||
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta);
|
||||
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
TextureRuntime& runtime;
|
||||
SurfaceCache surface_cache;
|
||||
PageMap cached_pages;
|
||||
SurfaceMap dirty_regions;
|
||||
SurfaceSet remove_surfaces;
|
||||
u16 resolution_scale_factor;
|
||||
std::unordered_map<TextureCubeConfig, Surface> texture_cube_cache;
|
||||
};
|
||||
|
||||
} // namespace VideoCore
|
10
src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
Normal file
10
src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "video_core/rasterizer_cache/rasterizer_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_texture_runtime.h"
|
||||
|
||||
namespace VideoCore {
|
||||
template class RasterizerCache<OpenGL::Traits>;
|
||||
}
|
@ -2,13 +2,15 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <bit>
|
||||
#include "common/microprofile.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/settings.h"
|
||||
#include "video_core/rasterizer_cache/utils.h"
|
||||
#include "video_core/renderer_opengl/gl_driver.h"
|
||||
#include "video_core/renderer_opengl/gl_format_reinterpreter.h"
|
||||
#include "video_core/renderer_opengl/gl_state.h"
|
||||
#include "video_core/renderer_opengl/gl_texture_runtime.h"
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
|
@ -3,9 +3,10 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include "video_core/rasterizer_cache/rasterizer_cache.h"
|
||||
#include "video_core/rasterizer_cache/rasterizer_cache_base.h"
|
||||
#include "video_core/rasterizer_cache/surface_base.h"
|
||||
#include "video_core/renderer_opengl/gl_format_reinterpreter.h"
|
||||
#include "video_core/renderer_opengl/gl_stream_buffer.h"
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/frontend/framebuffer_layout.h"
|
||||
|
10
src/video_core/renderer_vulkan/vk_rasterizer_cache.cpp
Normal file
10
src/video_core/renderer_vulkan/vk_rasterizer_cache.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "video_core/rasterizer_cache/rasterizer_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
|
||||
|
||||
namespace VideoCore {
|
||||
template class RasterizerCache<Vulkan::Traits>;
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <bit>
|
||||
#include "common/microprofile.h"
|
||||
#include "video_core/rasterizer_cache/texture_codec.h"
|
||||
#include "video_core/rasterizer_cache/utils.h"
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <vulkan/vulkan_hash.hpp>
|
||||
#include "video_core/rasterizer_cache/rasterizer_cache.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_format_reinterpreter.h"
|
||||
|
Reference in New Issue
Block a user