gl_framebuffer_cache: Implement framebuffer cache texture invalidation

This commit is contained in:
ReinUsesLisp
2019-04-02 20:46:23 -03:00
parent 2b22077aa4
commit d1ba243c9e
9 changed files with 92 additions and 27 deletions

View File

@@ -27,11 +27,11 @@ bool FramebufferCacheKey::operator==(const FramebufferCacheKey& rhs) const {
rhs.zeta);
}
FramebufferCacheOpenGL::FramebufferCacheOpenGL() = default;
FramebufferCacheOpenGLImpl::FramebufferCacheOpenGLImpl() = default;
FramebufferCacheOpenGL::~FramebufferCacheOpenGL() = default;
FramebufferCacheOpenGLImpl::~FramebufferCacheOpenGLImpl() = default;
GLuint FramebufferCacheOpenGL::GetFramebuffer(const FramebufferCacheKey& key) {
GLuint FramebufferCacheOpenGLImpl::GetFramebuffer(const FramebufferCacheKey& key) {
const auto [entry, is_cache_miss] = cache.try_emplace(key);
auto& framebuffer{entry->second};
if (is_cache_miss) {
@@ -40,7 +40,13 @@ GLuint FramebufferCacheOpenGL::GetFramebuffer(const FramebufferCacheKey& key) {
return framebuffer.handle;
}
OGLFramebuffer FramebufferCacheOpenGL::CreateFramebuffer(const FramebufferCacheKey& key) {
void FramebufferCacheOpenGLImpl::InvalidateTexture(GLuint texture) {
for (auto it = cache.begin(); it != cache.end();) {
it = TryTextureInvalidation(texture, it);
}
}
OGLFramebuffer FramebufferCacheOpenGLImpl::CreateFramebuffer(const FramebufferCacheKey& key) {
OGLFramebuffer framebuffer;
framebuffer.Create();
@@ -73,4 +79,19 @@ OGLFramebuffer FramebufferCacheOpenGL::CreateFramebuffer(const FramebufferCacheK
return framebuffer;
}
FramebufferCacheOpenGLImpl::CacheType::iterator FramebufferCacheOpenGLImpl::TryTextureInvalidation(
GLuint texture, CacheType::iterator it) {
const auto& [key, framebuffer] = *it;
const std::size_t count = key.is_single_buffer ? 1 : static_cast<std::size_t>(key.colors_count);
for (std::size_t i = 0; i < count; ++i) {
if (texture == key.colors[i]) {
return cache.erase(it);
}
}
if (texture == key.zeta) {
return cache.erase(it);
}
return ++it;
}
} // namespace OpenGL

View File

@@ -6,6 +6,7 @@
#include <array>
#include <cstddef>
#include <memory>
#include <unordered_map>
#include <glad/glad.h>
@@ -17,6 +18,9 @@
namespace OpenGL {
class FramebufferCacheOpenGLImpl;
using FramebufferCacheOpenGL = std::shared_ptr<FramebufferCacheOpenGLImpl>;
struct alignas(sizeof(u64)) FramebufferCacheKey {
bool is_single_buffer = false;
bool stencil_enable = false;
@@ -51,18 +55,28 @@ struct hash<OpenGL::FramebufferCacheKey> {
namespace OpenGL {
class FramebufferCacheOpenGL {
class FramebufferCacheOpenGLImpl {
public:
FramebufferCacheOpenGL();
~FramebufferCacheOpenGL();
FramebufferCacheOpenGLImpl();
~FramebufferCacheOpenGLImpl();
/// Returns and caches a framebuffer with the passed arguments.
GLuint GetFramebuffer(const FramebufferCacheKey& key);
/// Invalidates a texture inside the cache.
void InvalidateTexture(GLuint texture);
private:
using CacheType = std::unordered_map<FramebufferCacheKey, OGLFramebuffer>;
/// Returns a new framebuffer from the passed arguments.
OGLFramebuffer CreateFramebuffer(const FramebufferCacheKey& key);
/// Attempts to destroy the framebuffer cache entry in `it` and returns the next one.
CacheType::iterator TryTextureInvalidation(GLuint texture, CacheType::iterator it);
OpenGLState local_state;
std::unordered_map<FramebufferCacheKey, OGLFramebuffer> cache;
CacheType cache;
};
} // namespace OpenGL

View File

@@ -81,8 +81,10 @@ struct DrawParameters {
};
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
: res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system},
screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
: framebuffer_cache{std::make_shared<FramebufferCacheOpenGLImpl>()},
res_cache{*this, framebuffer_cache}, shader_cache{*this, system},
global_cache{*this}, system{system}, screen_info{info},
buffer_cache(*this, STREAM_BUFFER_SIZE) {
// Create sampler objects
for (std::size_t i = 0; i < texture_samplers.size(); ++i) {
texture_samplers[i].Create();
@@ -512,7 +514,7 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil;
}
current_state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(fbkey);
current_state.draw.draw_framebuffer = framebuffer_cache->GetFramebuffer(fbkey);
SyncViewport(current_state);
return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable};

View File

@@ -209,10 +209,10 @@ private:
OpenGLState state;
FramebufferCacheOpenGL framebuffer_cache;
RasterizerCacheOpenGL res_cache;
ShaderCacheOpenGL shader_cache;
GlobalRegionCacheOpenGL global_cache;
FramebufferCacheOpenGL framebuffer_cache;
Core::System& system;

View File

@@ -561,8 +561,9 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac
dst_surface->MarkAsModified(true, *this);
}
CachedSurface::CachedSurface(const SurfaceParams& params)
: RasterizerCacheObject{params.host_ptr}, params{params},
CachedSurface::CachedSurface(const SurfaceParams& params, FramebufferCacheOpenGL framebuffer_cache_)
: RasterizerCacheObject{params.host_ptr}, framebuffer_cache{std::move(framebuffer_cache_)},
texture{framebuffer_cache}, discrepant_view{framebuffer_cache}, params{params},
gl_target{SurfaceTargetToGL(params.target)}, cached_size_in_bytes{params.size_in_bytes} {
const auto optional_cpu_addr{
@@ -611,6 +612,8 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.gpu_addr, params.IdentityString());
}
CachedSurface::~CachedSurface() = default;
MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 192, 64));
void CachedSurface::LoadGLBuffer() {
MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
@@ -852,8 +855,9 @@ void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x,
}
}
RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer)
: RasterizerCache{rasterizer} {
RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer,
FramebufferCacheOpenGL framebuffer_cache)
: RasterizerCache{rasterizer}, framebuffer_cache{std::move(framebuffer_cache)} {
read_framebuffer.Create();
draw_framebuffer.Create();
copy_pbo.Create();
@@ -961,7 +965,7 @@ Surface RasterizerCacheOpenGL::GetUncachedSurface(const SurfaceParams& params) {
Surface surface{TryGetReservedSurface(params)};
if (!surface) {
// No reserved surface available, create a new one and reserve it
surface = std::make_shared<CachedSurface>(params);
surface = std::make_shared<CachedSurface>(params, framebuffer_cache);
ReserveSurface(surface);
}
return surface;

View File

@@ -18,6 +18,7 @@
#include "video_core/engines/fermi_2d.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_gen.h"
#include "video_core/surface.h"
@@ -350,7 +351,8 @@ class RasterizerOpenGL;
class CachedSurface final : public RasterizerCacheObject {
public:
explicit CachedSurface(const SurfaceParams& params);
explicit CachedSurface(const SurfaceParams& params, FramebufferCacheOpenGL framebuffer_cache_);
~CachedSurface();
VAddr GetCpuAddr() const override {
return cpu_addr;
@@ -426,6 +428,7 @@ private:
void EnsureTextureDiscrepantView();
FramebufferCacheOpenGL framebuffer_cache;
OGLTexture texture;
OGLTexture discrepant_view;
std::vector<std::vector<u8>> gl_buffer;
@@ -434,7 +437,7 @@ private:
GLenum gl_internal_format{};
std::size_t cached_size_in_bytes{};
std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
std::size_t memory_size;
std::size_t memory_size{};
bool reinterpreted = false;
bool must_reload = false;
VAddr cpu_addr{};
@@ -442,7 +445,8 @@ private:
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
public:
explicit RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer);
explicit RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer,
FramebufferCacheOpenGL framebuffer_cache);
/// Get a surface based on the texture configuration
Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config,
@@ -499,6 +503,8 @@ private:
/// destroyed when used with different surface parameters.
std::unordered_map<SurfaceReserveKey, Surface> surface_reserve;
FramebufferCacheOpenGL framebuffer_cache;
OGLFramebuffer read_framebuffer;
OGLFramebuffer draw_framebuffer;

View File

@@ -6,6 +6,7 @@
#include <glad/glad.h>
#include "common/common_types.h"
#include "common/microprofile.h"
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
#include "video_core/renderer_opengl/gl_state.h"
@@ -15,6 +16,16 @@ MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_R
namespace OpenGL {
OGLTexture::OGLTexture(FramebufferCacheOpenGL framebuffer_cache)
: framebuffer_cache{std::move(framebuffer_cache)} {}
OGLTexture::OGLTexture(OGLTexture&& o) noexcept
: handle{std::exchange(o.handle, 0)}, framebuffer_cache{std::move(o.framebuffer_cache)} {}
OGLTexture::~OGLTexture() {
Release();
}
void OGLTexture::Create(GLenum target) {
if (handle != 0)
return;
@@ -28,6 +39,9 @@ void OGLTexture::Release() {
return;
MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
if (framebuffer_cache) {
framebuffer_cache->InvalidateTexture(handle);
}
glDeleteTextures(1, &handle);
OpenGLState::GetCurState().UnbindTexture(handle).Apply();
handle = 0;

View File

@@ -4,6 +4,7 @@
#pragma once
#include <memory>
#include <utility>
#include <glad/glad.h>
#include "common/common_types.h"
@@ -11,15 +12,15 @@
namespace OpenGL {
class FramebufferCacheOpenGLImpl;
using FramebufferCacheOpenGL = std::shared_ptr<FramebufferCacheOpenGLImpl>;
class OGLTexture : private NonCopyable {
public:
OGLTexture() = default;
explicit OGLTexture(FramebufferCacheOpenGL framebuffer_cache);
OGLTexture(OGLTexture&& o) noexcept;
OGLTexture(OGLTexture&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
~OGLTexture() {
Release();
}
~OGLTexture();
OGLTexture& operator=(OGLTexture&& o) noexcept {
Release();
@@ -34,6 +35,9 @@ public:
void Release();
GLuint handle = 0;
private:
FramebufferCacheOpenGL framebuffer_cache;
};
class OGLSampler : private NonCopyable {

View File

@@ -28,7 +28,7 @@ namespace OpenGL {
/// Structure used for storing information about the textures for the Switch screen
struct TextureInfo {
OGLTexture resource;
OGLTexture resource{nullptr};
GLsizei width;
GLsizei height;
GLenum gl_format;