video_core: Move UpdatePagesCachedCount to RasterizerAccelerated

This commit is contained in:
emufan4568
2022-09-06 21:01:15 +03:00
committed by GPUCode
parent 0fe61ba040
commit db7cdb741c
7 changed files with 114 additions and 44 deletions

View File

@@ -13,6 +13,8 @@ add_library(video_core STATIC
precompiled_headers.h precompiled_headers.h
primitive_assembly.cpp primitive_assembly.cpp
primitive_assembly.h primitive_assembly.h
rasterizer_accelerated.cpp
rasterizer_accelerated.h
rasterizer_interface.h rasterizer_interface.h
regs.cpp regs.cpp
regs.h regs.h

View File

@@ -0,0 +1,74 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <limits>
#include "core/memory.h"
#include "video_core/video_core.h"
#include "video_core/rasterizer_accelerated.h"
namespace VideoCore {
void RasterizerAccelerated::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) {
const u32 page_start = addr >> Memory::CITRA_PAGE_BITS;
const u32 page_end = ((addr + size - 1) >> Memory::CITRA_PAGE_BITS);
u32 uncache_start_addr = 0;
u32 cache_start_addr = 0;
u32 uncache_bytes = 0;
u32 cache_bytes = 0;
for (u32 page = page_start; page != page_end; page++) {
auto& count = cached_pages.at(page);
// Ensure no overflow happens
if (delta > 0) {
ASSERT_MSG(count < std::numeric_limits<u16>::max(), "Count will overflow!");
} else if (delta < 0) {
ASSERT_MSG(count > 0, "Count will underflow!");
} else {
ASSERT_MSG(false, "Delta must be non-zero!");
}
// Adds or subtracts 1, as count is a unsigned 8-bit value
count += delta;
// Assume delta is either -1 or 1
if (count == 0) {
if (uncache_bytes == 0) {
uncache_start_addr = page << Memory::CITRA_PAGE_BITS;
}
uncache_bytes += Memory::CITRA_PAGE_SIZE;
} else if (uncache_bytes > 0) {
VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes,
false);
uncache_bytes = 0;
}
if (count == 1 && delta > 0) {
if (cache_bytes == 0) {
cache_start_addr = page << Memory::CITRA_PAGE_BITS;
}
cache_bytes += Memory::CITRA_PAGE_SIZE;
} else if (cache_bytes > 0) {
VideoCore::g_memory->RasterizerMarkRegionCached(cache_start_addr, cache_bytes,
true);
cache_bytes = 0;
}
}
if (uncache_bytes > 0) {
VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes,
false);
}
if (cache_bytes > 0) {
VideoCore::g_memory->RasterizerMarkRegionCached(cache_start_addr, cache_bytes,
true);
}
}
} // namespace VideoCore

View File

@@ -0,0 +1,19 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "video_core/rasterizer_interface.h"
namespace VideoCore {
class RasterizerAccelerated : public RasterizerInterface {
public:
virtual ~RasterizerAccelerated() = default;
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta) override;
private:
std::array<u16, 0x30000> cached_pages;
};
} // namespace VideoCore

View File

@@ -8,6 +8,7 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/microprofile.h" #include "common/microprofile.h"
#include "video_core/pica_state.h" #include "video_core/pica_state.h"
#include "video_core/rasterizer_accelerated.h"
#include "video_core/rasterizer_cache/rasterizer_cache.h" #include "video_core/rasterizer_cache/rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_format_reinterpreter.h" #include "video_core/renderer_opengl/gl_format_reinterpreter.h"
#include "video_core/renderer_opengl/texture_downloader_es.h" #include "video_core/renderer_opengl/texture_downloader_es.h"
@@ -239,7 +240,8 @@ static Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams&
return match_surface; return match_surface;
} }
RasterizerCacheOpenGL::RasterizerCacheOpenGL() { RasterizerCacheOpenGL::RasterizerCacheOpenGL(VideoCore::RasterizerAccelerated& rasterizer)
: rasterizer(rasterizer) {
resolution_scale_factor = VideoCore::GetResolutionScaleFactor(); resolution_scale_factor = VideoCore::GetResolutionScaleFactor();
texture_filterer = std::make_unique<TextureFilterer>( texture_filterer = std::make_unique<TextureFilterer>(
Settings::values.texture_filter_name.GetValue(), resolution_scale_factor); Settings::values.texture_filter_name.GetValue(), resolution_scale_factor);
@@ -1055,7 +1057,7 @@ void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) {
} }
surface->registered = true; surface->registered = true;
surface_cache.add({surface->GetInterval(), SurfaceSet{surface}}); surface_cache.add({surface->GetInterval(), SurfaceSet{surface}});
UpdatePagesCachedCount(surface->addr, surface->size, 1); rasterizer.UpdatePagesCachedCount(surface->addr, surface->size, 1);
} }
void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) {
@@ -1065,42 +1067,8 @@ void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) {
return; return;
} }
surface->registered = false; surface->registered = false;
UpdatePagesCachedCount(surface->addr, surface->size, -1); rasterizer.UpdatePagesCachedCount(surface->addr, surface->size, -1);
surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}}); surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}});
} }
void RasterizerCacheOpenGL::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) {
const u32 num_pages =
((addr + size - 1) >> Memory::CITRA_PAGE_BITS) - (addr >> Memory::CITRA_PAGE_BITS) + 1;
const u32 page_start = addr >> Memory::CITRA_PAGE_BITS;
const u32 page_end = page_start + num_pages;
// Interval maps will erase segments if count reaches 0, so if delta is negative we have to
// subtract after iterating
const auto pages_interval = PageMap::interval_type::right_open(page_start, page_end);
if (delta > 0)
cached_pages.add({pages_interval, delta});
for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
const auto interval = pair.first & pages_interval;
const int count = pair.second;
const PAddr interval_start_addr = boost::icl::first(interval) << Memory::CITRA_PAGE_BITS;
const PAddr interval_end_addr = boost::icl::last_next(interval) << Memory::CITRA_PAGE_BITS;
const u32 interval_size = interval_end_addr - interval_start_addr;
if (delta > 0 && count == delta)
VideoCore::g_memory->RasterizerMarkRegionCached(interval_start_addr, interval_size,
true);
else if (delta < 0 && count == -delta)
VideoCore::g_memory->RasterizerMarkRegionCached(interval_start_addr, interval_size,
false);
else
ASSERT(count >= 0);
}
if (delta < 0)
cached_pages.add({pages_interval, delta});
}
} // namespace OpenGL } // namespace OpenGL

View File

@@ -9,6 +9,10 @@
#include "video_core/rasterizer_cache/surface_params.h" #include "video_core/rasterizer_cache/surface_params.h"
#include "video_core/texture/texture_decode.h" #include "video_core/texture/texture_decode.h"
namespace VideoCore {
class RasterizerAccelerated;
}
namespace OpenGL { namespace OpenGL {
enum class ScaleMatch { enum class ScaleMatch {
@@ -23,7 +27,7 @@ class FormatReinterpreterOpenGL;
class RasterizerCacheOpenGL : NonCopyable { class RasterizerCacheOpenGL : NonCopyable {
public: public:
RasterizerCacheOpenGL(); RasterizerCacheOpenGL(VideoCore::RasterizerAccelerated& rasterizer);
~RasterizerCacheOpenGL(); ~RasterizerCacheOpenGL();
/// Blit one surface's texture to another /// Blit one surface's texture to another
@@ -105,9 +109,7 @@ private:
/// Remove surface from the cache /// Remove surface from the cache
void UnregisterSurface(const Surface& surface); void UnregisterSurface(const Surface& surface);
/// Increase/decrease the number of surface in pages touching the specified region VideoCore::RasterizerAccelerated& rasterizer;
void UpdatePagesCachedCount(PAddr addr, u32 size, int delta);
TextureRuntime runtime; TextureRuntime runtime;
SurfaceCache surface_cache; SurfaceCache surface_cache;
PageMap cached_pages; PageMap cached_pages;

View File

@@ -29,7 +29,7 @@ using DiskResourceLoadCallback = std::function<void(LoadCallbackStage, std::size
class RasterizerInterface { class RasterizerInterface {
public: public:
virtual ~RasterizerInterface() {} virtual ~RasterizerInterface() = default;
/// Queues the primitive formed by the given vertices for rendering /// Queues the primitive formed by the given vertices for rendering
virtual void AddTriangle(const Pica::Shader::OutputVertex& v0, virtual void AddTriangle(const Pica::Shader::OutputVertex& v0,
@@ -85,9 +85,14 @@ public:
return false; return false;
} }
/// Increase/decrease the number of surface in pages touching the specified region
virtual void UpdatePagesCachedCount(PAddr addr, u32 size, int delta) {}
/// Loads disk cached rasterizer data before rendering
virtual void LoadDiskResources(const std::atomic_bool& stop_loading, virtual void LoadDiskResources(const std::atomic_bool& stop_loading,
const DiskResourceLoadCallback& callback) {} const DiskResourceLoadCallback& callback) {}
/// Synchronizes the graphics API state with the PICA state
virtual void SyncEntireState() {} virtual void SyncEntireState() {}
}; };
} // namespace VideoCore } // namespace VideoCore

View File

@@ -7,7 +7,7 @@
#include "core/hw/gpu.h" #include "core/hw/gpu.h"
#include "video_core/pica_types.h" #include "video_core/pica_types.h"
#include "video_core/rasterizer_cache/rasterizer_cache.h" #include "video_core/rasterizer_cache/rasterizer_cache.h"
#include "video_core/rasterizer_interface.h" #include "video_core/rasterizer_accelerated.h"
#include "video_core/regs_lighting.h" #include "video_core/regs_lighting.h"
#include "video_core/regs_texturing.h" #include "video_core/regs_texturing.h"
#include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/gl_shader_manager.h"
@@ -22,7 +22,7 @@ class EmuWindow;
namespace OpenGL { namespace OpenGL {
class ShaderProgramManager; class ShaderProgramManager;
class RasterizerOpenGL : public VideoCore::RasterizerInterface { class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
public: public:
explicit RasterizerOpenGL(Frontend::EmuWindow& emu_window); explicit RasterizerOpenGL(Frontend::EmuWindow& emu_window);
~RasterizerOpenGL() override; ~RasterizerOpenGL() override;