gl_rasterizer_cache: Use GPUVAddr as cache key, not parameter set.

This commit is contained in:
bunnei 2018-07-21 14:36:32 -04:00
parent cd47391c2d
commit 4301f0b539
3 changed files with 46 additions and 57 deletions

View file

@ -413,11 +413,13 @@ void RasterizerOpenGL::Clear() {
glClear(clear_mask); glClear(clear_mask);
// Mark framebuffer surfaces as dirty // Mark framebuffer surfaces as dirty
if (dirty_color_surface != nullptr) { if (Settings::values.use_accurate_framebuffers) {
res_cache.MarkSurfaceAsDirty(dirty_color_surface); if (dirty_color_surface != nullptr) {
} res_cache.FlushSurface(dirty_color_surface);
if (dirty_depth_surface != nullptr) { }
res_cache.MarkSurfaceAsDirty(dirty_depth_surface); if (dirty_depth_surface != nullptr) {
res_cache.FlushSurface(dirty_depth_surface);
}
} }
} }
@ -520,11 +522,13 @@ void RasterizerOpenGL::DrawArrays() {
state.Apply(); state.Apply();
// Mark framebuffer surfaces as dirty // Mark framebuffer surfaces as dirty
if (dirty_color_surface != nullptr) { if (Settings::values.use_accurate_framebuffers) {
res_cache.MarkSurfaceAsDirty(dirty_color_surface); if (dirty_color_surface != nullptr) {
} res_cache.FlushSurface(dirty_color_surface);
if (dirty_depth_surface != nullptr) { }
res_cache.MarkSurfaceAsDirty(dirty_depth_surface); if (dirty_depth_surface != nullptr) {
res_cache.FlushSurface(dirty_depth_surface);
}
} }
} }

View file

@ -565,17 +565,9 @@ void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) {
surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle);
} }
void RasterizerCacheOpenGL::MarkSurfaceAsDirty(const Surface& surface) { void RasterizerCacheOpenGL::FlushSurface(const Surface& surface) {
if (Settings::values.use_accurate_framebuffers) { surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle);
// If enabled, always flush dirty surfaces surface->FlushGLBuffer();
surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle);
surface->FlushGLBuffer();
} else {
// Otherwise, don't mark surfaces that we write to as cached, because the resulting loads
// and flushes are very slow and do not seem to improve accuracy
const auto& params{surface->GetSurfaceParams()};
Memory::RasterizerMarkRegionCached(params.addr, params.size_in_bytes, false);
}
} }
Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {
@ -589,21 +581,22 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {
return {}; return {};
// Check for an exact match in existing surfaces // Check for an exact match in existing surfaces
const auto& surface_key{SurfaceKey::Create(params)}; const auto& search{surface_cache.find(params.addr)};
const auto& search{surface_cache.find(surface_key)};
Surface surface; Surface surface;
if (search != surface_cache.end()) { if (search != surface_cache.end()) {
surface = search->second; surface = search->second;
if (Settings::values.use_accurate_framebuffers) { if (surface->GetSurfaceParams() != params || Settings::values.use_accurate_framebuffers) {
// Reload the surface from Switch memory FlushSurface(surface);
LoadSurface(surface); UnregisterSurface(surface);
} else {
return surface;
} }
} else {
surface = std::make_shared<CachedSurface>(params);
RegisterSurface(surface);
LoadSurface(surface);
} }
surface = std::make_shared<CachedSurface>(params);
RegisterSurface(surface);
LoadSurface(surface);
return surface; return surface;
} }
@ -652,22 +645,20 @@ void RasterizerCacheOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, size_t size)
void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) {
const auto& params{surface->GetSurfaceParams()}; const auto& params{surface->GetSurfaceParams()};
const auto& surface_key{SurfaceKey::Create(params)}; const auto& search{surface_cache.find(params.addr)};
const auto& search{surface_cache.find(surface_key)};
if (search != surface_cache.end()) { if (search != surface_cache.end()) {
// Registered already // Registered already
return; return;
} }
surface_cache[surface_key] = surface; surface_cache[params.addr] = surface;
UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1); UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1);
} }
void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) {
const auto& params{surface->GetSurfaceParams()}; const auto& params{surface->GetSurfaceParams()};
const auto& surface_key{SurfaceKey::Create(params)}; const auto& search{surface_cache.find(params.addr)};
const auto& search{surface_cache.find(surface_key)};
if (search == surface_cache.end()) { if (search == surface_cache.end()) {
// Unregistered already // Unregistered already

View file

@ -10,7 +10,6 @@
#include <vector> #include <vector>
#include <boost/icl/interval_map.hpp> #include <boost/icl/interval_map.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/hash.h"
#include "common/math_util.h" #include "common/math_util.h"
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_resource_manager.h"
@ -137,6 +136,7 @@ struct SurfaceParams {
ASSERT(static_cast<size_t>(format) < bpp_table.size()); ASSERT(static_cast<size_t>(format) < bpp_table.size());
return bpp_table[static_cast<size_t>(format)]; return bpp_table[static_cast<size_t>(format)];
} }
u32 GetFormatBpp() const { u32 GetFormatBpp() const {
return GetFormatBpp(pixel_format); return GetFormatBpp(pixel_format);
} }
@ -369,6 +369,18 @@ struct SurfaceParams {
Tegra::GPUVAddr zeta_address, Tegra::GPUVAddr zeta_address,
Tegra::DepthFormat format); Tegra::DepthFormat format);
bool operator==(const SurfaceParams& other) const {
return std::tie(addr, is_tiled, block_height, pixel_format, component_type, type, width,
height, unaligned_height, size_in_bytes) ==
std::tie(other.addr, other.is_tiled, other.block_height, other.pixel_format,
other.component_type, other.type, other.width, other.height,
other.unaligned_height, other.size_in_bytes);
}
bool operator!=(const SurfaceParams& other) const {
return !operator==(other);
}
Tegra::GPUVAddr addr; Tegra::GPUVAddr addr;
bool is_tiled; bool is_tiled;
u32 block_height; u32 block_height;
@ -381,24 +393,6 @@ struct SurfaceParams {
size_t size_in_bytes; size_t size_in_bytes;
}; };
/// Hashable variation of SurfaceParams, used for a key in the surface cache
struct SurfaceKey : Common::HashableStruct<SurfaceParams> {
static SurfaceKey Create(const SurfaceParams& params) {
SurfaceKey res;
res.state = params;
return res;
}
};
namespace std {
template <>
struct hash<SurfaceKey> {
size_t operator()(const SurfaceKey& k) const {
return k.Hash();
}
};
} // namespace std
class CachedSurface final { class CachedSurface final {
public: public:
CachedSurface(const SurfaceParams& params); CachedSurface(const SurfaceParams& params);
@ -444,8 +438,8 @@ public:
SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
const MathUtil::Rectangle<s32>& viewport); const MathUtil::Rectangle<s32>& viewport);
/// Marks the specified surface as "dirty", in that it is out of sync with Switch memory /// Flushes the surface to Switch memory
void MarkSurfaceAsDirty(const Surface& surface); void FlushSurface(const Surface& surface);
/// Tries to find a framebuffer GPU address based on the provided CPU address /// Tries to find a framebuffer GPU address based on the provided CPU address
Surface TryFindFramebufferSurface(VAddr cpu_addr) const; Surface TryFindFramebufferSurface(VAddr cpu_addr) const;
@ -469,7 +463,7 @@ private:
/// Increase/decrease the number of surface in pages touching the specified region /// Increase/decrease the number of surface in pages touching the specified region
void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta);
std::unordered_map<SurfaceKey, Surface> surface_cache; std::unordered_map<Tegra::GPUVAddr, Surface> surface_cache;
PageMap cached_pages; PageMap cached_pages;
OGLFramebuffer read_framebuffer; OGLFramebuffer read_framebuffer;