From b0880f0ef898288a97fc9f1f3571ca20f7b6da43 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Mon, 6 Feb 2023 22:52:18 +0200 Subject: [PATCH] video_core: Move rasterizer cache template definitions to separate file * Helps with build times --- src/video_core/CMakeLists.txt | 3 + .../rasterizer_cache/rasterizer_cache.h | 165 +--------------- .../rasterizer_cache/rasterizer_cache_base.h | 177 ++++++++++++++++++ .../renderer_opengl/gl_rasterizer_cache.cpp | 10 + .../renderer_opengl/gl_texture_runtime.cpp | 4 +- .../renderer_opengl/gl_texture_runtime.h | 3 +- .../renderer_vulkan/renderer_vulkan.cpp | 1 + .../renderer_vulkan/vk_rasterizer_cache.cpp | 10 + .../renderer_vulkan/vk_texture_runtime.cpp | 1 - .../renderer_vulkan/vk_texture_runtime.h | 2 +- 10 files changed, 208 insertions(+), 168 deletions(-) create mode 100644 src/video_core/rasterizer_cache/rasterizer_cache_base.h create mode 100644 src/video_core/renderer_opengl/gl_rasterizer_cache.cpp create mode 100644 src/video_core/renderer_vulkan/vk_rasterizer_cache.cpp diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index c71d4fb19..816d4440f 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -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 diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index ebfb6b7ac..c3a361505 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -4,179 +4,16 @@ #pragma once -#include -#include -#include -#include -#include #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 RasterizerCache : NonCopyable { -public: - using TextureRuntime = typename T::RuntimeType; - using Surface = std::shared_ptr; - using Watcher = SurfaceWatcher; - -private: - /// Declare rasterizer interval types - using SurfaceSet = std::set; - using SurfaceMap = boost::icl::interval_map; - using SurfaceCache = boost::icl::interval_map; - - static_assert( - std::is_same() && - std::is_same(), - "Incorrect interval types"); - - using SurfaceRect_Tuple = std::tuple>; - using SurfaceSurfaceRect_Tuple = std::tuple>; - using PageMap = boost::icl::interval_map; - -public: - RasterizerCache(Memory::MemorySystem& memory, TextureRuntime& runtime); - ~RasterizerCache() = default; - - /// Get the best surface match (and its match type) for the given flags - template - Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params, - ScaleMatch match_scale_type, - std::optional validate_interval = std::nullopt); - - /// Blit one surface's texture to another - bool BlitSurfaces(const Surface& src_surface, Common::Rectangle src_rect, - const Surface& dst_surface, Common::Rectangle 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& 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 texture_cube_cache; -}; - template RasterizerCache::RasterizerCache(Memory::MemorySystem& memory_, TextureRuntime& runtime_) : memory{memory_}, runtime{runtime_}, resolution_scale_factor{ diff --git a/src/video_core/rasterizer_cache/rasterizer_cache_base.h b/src/video_core/rasterizer_cache/rasterizer_cache_base.h new file mode 100644 index 000000000..eba74c0cd --- /dev/null +++ b/src/video_core/rasterizer_cache/rasterizer_cache_base.h @@ -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 +#include +#include +#include +#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 RasterizerCache : NonCopyable { +public: + using TextureRuntime = typename T::RuntimeType; + using Surface = std::shared_ptr; + using Watcher = SurfaceWatcher; + +private: + /// Declare rasterizer interval types + using SurfaceSet = std::set; + using SurfaceMap = boost::icl::interval_map; + using SurfaceCache = boost::icl::interval_map; + + static_assert( + std::is_same() && + std::is_same(), + "Incorrect interval types"); + + using SurfaceRect_Tuple = std::tuple>; + using SurfaceSurfaceRect_Tuple = std::tuple>; + using PageMap = boost::icl::interval_map; + +public: + RasterizerCache(Memory::MemorySystem& memory, TextureRuntime& runtime); + ~RasterizerCache() = default; + + /// Get the best surface match (and its match type) for the given flags + template + Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params, + ScaleMatch match_scale_type, + std::optional validate_interval = std::nullopt); + + /// Blit one surface's texture to another + bool BlitSurfaces(const Surface& src_surface, Common::Rectangle src_rect, + const Surface& dst_surface, Common::Rectangle 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& 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 texture_cube_cache; +}; + +} // namespace VideoCore diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp new file mode 100644 index 000000000..fd9bb952a --- /dev/null +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -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; +} diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index abee3de44..91322fd99 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -2,13 +2,15 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#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 { diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.h b/src/video_core/renderer_opengl/gl_texture_runtime.h index ed2a423b7..b5cc0b573 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.h +++ b/src/video_core/renderer_opengl/gl_texture_runtime.h @@ -3,9 +3,10 @@ // Refer to the license.txt file included. #pragma once + #include #include -#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" diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 1f8861772..d88424df6 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -6,6 +6,7 @@ #include #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" diff --git a/src/video_core/renderer_vulkan/vk_rasterizer_cache.cpp b/src/video_core/renderer_vulkan/vk_rasterizer_cache.cpp new file mode 100644 index 000000000..55e4b7e7a --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_rasterizer_cache.cpp @@ -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; +} diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index 06709957b..d84406272 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -2,7 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include #include "common/microprofile.h" #include "video_core/rasterizer_cache/texture_codec.h" #include "video_core/rasterizer_cache/utils.h" diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.h b/src/video_core/renderer_vulkan/vk_texture_runtime.h index a37a842e9..e34710785 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.h +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.h @@ -7,7 +7,7 @@ #include #include #include -#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"