diff options
| author | 2019-05-11 03:15:49 -0300 | |
|---|---|---|
| committer | 2019-06-20 21:36:12 -0300 | |
| commit | 9098905dd13bb68f2fe49a9590688b76cc999fdd (patch) | |
| tree | 496c5711a40b37341765aedba0aebb458748beea /src | |
| parent | texture_cache return invalid buffer on deactivated color_mask (diff) | |
| download | yuzu-9098905dd13bb68f2fe49a9590688b76cc999fdd.tar.gz yuzu-9098905dd13bb68f2fe49a9590688b76cc999fdd.tar.xz yuzu-9098905dd13bb68f2fe49a9590688b76cc999fdd.zip | |
gl_framebuffer_cache: Use a hashed struct to cache framebuffers
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_framebuffer_cache.cpp | 73 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_framebuffer_cache.h | 68 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 59 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 6 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 2 |
6 files changed, 148 insertions, 62 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 470fbceda..9d43f03d2 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -41,6 +41,8 @@ add_library(video_core STATIC | |||
| 41 | renderer_opengl/gl_buffer_cache.h | 41 | renderer_opengl/gl_buffer_cache.h |
| 42 | renderer_opengl/gl_device.cpp | 42 | renderer_opengl/gl_device.cpp |
| 43 | renderer_opengl/gl_device.h | 43 | renderer_opengl/gl_device.h |
| 44 | renderer_opengl/gl_framebuffer_cache.cpp | ||
| 45 | renderer_opengl/gl_framebuffer_cache.h | ||
| 44 | renderer_opengl/gl_global_cache.cpp | 46 | renderer_opengl/gl_global_cache.cpp |
| 45 | renderer_opengl/gl_global_cache.h | 47 | renderer_opengl/gl_global_cache.h |
| 46 | renderer_opengl/gl_rasterizer.cpp | 48 | renderer_opengl/gl_rasterizer.cpp |
diff --git a/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp b/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp new file mode 100644 index 000000000..bb9f9b81f --- /dev/null +++ b/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <tuple> | ||
| 6 | |||
| 7 | #include "common/cityhash.h" | ||
| 8 | #include "common/scope_exit.h" | ||
| 9 | #include "video_core/engines/maxwell_3d.h" | ||
| 10 | #include "video_core/renderer_opengl/gl_framebuffer_cache.h" | ||
| 11 | #include "video_core/renderer_opengl/gl_state.h" | ||
| 12 | |||
| 13 | namespace OpenGL { | ||
| 14 | |||
| 15 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | ||
| 16 | |||
| 17 | FramebufferCacheOpenGL::FramebufferCacheOpenGL() = default; | ||
| 18 | |||
| 19 | FramebufferCacheOpenGL::~FramebufferCacheOpenGL() = default; | ||
| 20 | |||
| 21 | GLuint FramebufferCacheOpenGL::GetFramebuffer(const FramebufferCacheKey& key) { | ||
| 22 | const auto [entry, is_cache_miss] = cache.try_emplace(key); | ||
| 23 | auto& framebuffer{entry->second}; | ||
| 24 | if (is_cache_miss) { | ||
| 25 | framebuffer = CreateFramebuffer(key); | ||
| 26 | } | ||
| 27 | return framebuffer.handle; | ||
| 28 | } | ||
| 29 | |||
| 30 | OGLFramebuffer FramebufferCacheOpenGL::CreateFramebuffer(const FramebufferCacheKey& key) { | ||
| 31 | OGLFramebuffer framebuffer; | ||
| 32 | framebuffer.Create(); | ||
| 33 | |||
| 34 | // TODO(Rodrigo): Use DSA here after Nvidia fixes their framebuffer DSA bugs. | ||
| 35 | local_state.draw.draw_framebuffer = framebuffer.handle; | ||
| 36 | local_state.ApplyFramebufferState(); | ||
| 37 | |||
| 38 | if (key.is_single_buffer) { | ||
| 39 | if (key.color_attachments[0] != GL_NONE && key.colors[0]) { | ||
| 40 | key.colors[0]->Attach(key.color_attachments[0]); | ||
| 41 | glDrawBuffer(key.color_attachments[0]); | ||
| 42 | } else { | ||
| 43 | glDrawBuffer(GL_NONE); | ||
| 44 | } | ||
| 45 | } else { | ||
| 46 | for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { | ||
| 47 | if (key.colors[index]) { | ||
| 48 | key.colors[index]->Attach(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index)); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | glDrawBuffers(key.colors_count, key.color_attachments.data()); | ||
| 52 | } | ||
| 53 | |||
| 54 | if (key.zeta) { | ||
| 55 | key.zeta->Attach(key.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT); | ||
| 56 | } | ||
| 57 | |||
| 58 | return framebuffer; | ||
| 59 | } | ||
| 60 | |||
| 61 | std::size_t FramebufferCacheKey::Hash() const { | ||
| 62 | static_assert(sizeof(*this) % sizeof(u64) == 0, "Unaligned struct"); | ||
| 63 | return static_cast<std::size_t>( | ||
| 64 | Common::CityHash64(reinterpret_cast<const char*>(this), sizeof(*this))); | ||
| 65 | } | ||
| 66 | |||
| 67 | bool FramebufferCacheKey::operator==(const FramebufferCacheKey& rhs) const { | ||
| 68 | return std::tie(is_single_buffer, stencil_enable, colors_count, color_attachments, colors, | ||
| 69 | zeta) == std::tie(rhs.is_single_buffer, rhs.stencil_enable, rhs.colors_count, | ||
| 70 | rhs.color_attachments, rhs.colors, rhs.zeta); | ||
| 71 | } | ||
| 72 | |||
| 73 | } // namespace OpenGL | ||
diff --git a/src/video_core/renderer_opengl/gl_framebuffer_cache.h b/src/video_core/renderer_opengl/gl_framebuffer_cache.h new file mode 100644 index 000000000..a3a996353 --- /dev/null +++ b/src/video_core/renderer_opengl/gl_framebuffer_cache.h | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | ||
| 9 | #include <unordered_map> | ||
| 10 | |||
| 11 | #include <glad/glad.h> | ||
| 12 | |||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "video_core/engines/maxwell_3d.h" | ||
| 15 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 16 | #include "video_core/renderer_opengl/gl_state.h" | ||
| 17 | #include "video_core/renderer_opengl/gl_texture_cache.h" | ||
| 18 | |||
| 19 | namespace OpenGL { | ||
| 20 | |||
| 21 | struct alignas(sizeof(u64)) FramebufferCacheKey { | ||
| 22 | bool is_single_buffer = false; | ||
| 23 | bool stencil_enable = false; | ||
| 24 | u16 colors_count = 0; | ||
| 25 | |||
| 26 | std::array<GLenum, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> color_attachments{}; | ||
| 27 | std::array<View, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors; | ||
| 28 | View zeta; | ||
| 29 | |||
| 30 | std::size_t Hash() const; | ||
| 31 | |||
| 32 | bool operator==(const FramebufferCacheKey& rhs) const; | ||
| 33 | |||
| 34 | bool operator!=(const FramebufferCacheKey& rhs) const { | ||
| 35 | return !operator==(rhs); | ||
| 36 | } | ||
| 37 | }; | ||
| 38 | |||
| 39 | } // namespace OpenGL | ||
| 40 | |||
| 41 | namespace std { | ||
| 42 | |||
| 43 | template <> | ||
| 44 | struct hash<OpenGL::FramebufferCacheKey> { | ||
| 45 | std::size_t operator()(const OpenGL::FramebufferCacheKey& k) const noexcept { | ||
| 46 | return k.Hash(); | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | |||
| 50 | } // namespace std | ||
| 51 | |||
| 52 | namespace OpenGL { | ||
| 53 | |||
| 54 | class FramebufferCacheOpenGL { | ||
| 55 | public: | ||
| 56 | FramebufferCacheOpenGL(); | ||
| 57 | ~FramebufferCacheOpenGL(); | ||
| 58 | |||
| 59 | GLuint GetFramebuffer(const FramebufferCacheKey& key); | ||
| 60 | |||
| 61 | private: | ||
| 62 | OGLFramebuffer CreateFramebuffer(const FramebufferCacheKey& key); | ||
| 63 | |||
| 64 | OpenGLState local_state; | ||
| 65 | std::unordered_map<FramebufferCacheKey, OGLFramebuffer> cache; | ||
| 66 | }; | ||
| 67 | |||
| 68 | } // namespace OpenGL | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 2872dbdeb..8218c5143 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -78,26 +78,6 @@ struct DrawParameters { | |||
| 78 | } | 78 | } |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | struct FramebufferCacheKey { | ||
| 82 | bool is_single_buffer = false; | ||
| 83 | bool stencil_enable = false; | ||
| 84 | |||
| 85 | std::array<GLenum, Maxwell::NumRenderTargets> color_attachments{}; | ||
| 86 | std::array<View, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors{}; | ||
| 87 | u32 colors_count = 0; | ||
| 88 | |||
| 89 | View zeta = nullptr; | ||
| 90 | |||
| 91 | auto Tie() const { | ||
| 92 | return std::tie(is_single_buffer, stencil_enable, color_attachments, colors, colors_count, | ||
| 93 | zeta); | ||
| 94 | } | ||
| 95 | |||
| 96 | bool operator<(const FramebufferCacheKey& rhs) const { | ||
| 97 | return Tie() < rhs.Tie(); | ||
| 98 | } | ||
| 99 | }; | ||
| 100 | |||
| 101 | RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, | 81 | RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, |
| 102 | ScreenInfo& info) | 82 | ScreenInfo& info) |
| 103 | : texture_cache{system, *this}, shader_cache{*this, system, emu_window, device}, | 83 | : texture_cache{system, *this}, shader_cache{*this, system, emu_window, device}, |
| @@ -355,42 +335,6 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 355 | gpu.dirty_flags.shaders = false; | 335 | gpu.dirty_flags.shaders = false; |
| 356 | } | 336 | } |
| 357 | 337 | ||
| 358 | void RasterizerOpenGL::SetupCachedFramebuffer(const FramebufferCacheKey& fbkey, | ||
| 359 | OpenGLState& current_state) { | ||
| 360 | const auto [entry, is_cache_miss] = framebuffer_cache.try_emplace(fbkey); | ||
| 361 | auto& framebuffer = entry->second; | ||
| 362 | |||
| 363 | if (is_cache_miss) | ||
| 364 | framebuffer.Create(); | ||
| 365 | |||
| 366 | current_state.draw.draw_framebuffer = framebuffer.handle; | ||
| 367 | current_state.ApplyFramebufferState(); | ||
| 368 | |||
| 369 | if (!is_cache_miss) | ||
| 370 | return; | ||
| 371 | |||
| 372 | if (fbkey.is_single_buffer) { | ||
| 373 | if (fbkey.color_attachments[0] != GL_NONE && fbkey.colors[0]) { | ||
| 374 | fbkey.colors[0]->Attach(fbkey.color_attachments[0]); | ||
| 375 | glDrawBuffer(fbkey.color_attachments[0]); | ||
| 376 | } else { | ||
| 377 | glDrawBuffer(GL_NONE); | ||
| 378 | } | ||
| 379 | } else { | ||
| 380 | for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { | ||
| 381 | if (fbkey.colors[index]) { | ||
| 382 | fbkey.colors[index]->Attach(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index)); | ||
| 383 | } | ||
| 384 | } | ||
| 385 | glDrawBuffers(fbkey.colors_count, fbkey.color_attachments.data()); | ||
| 386 | } | ||
| 387 | |||
| 388 | if (fbkey.zeta) { | ||
| 389 | fbkey.zeta->Attach(fbkey.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT | ||
| 390 | : GL_DEPTH_ATTACHMENT); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { | 338 | std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { |
| 395 | const auto& regs = system.GPU().Maxwell3D().regs; | 339 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 396 | 340 | ||
| @@ -556,7 +500,7 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers( | |||
| 556 | depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil; | 500 | depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil; |
| 557 | } | 501 | } |
| 558 | 502 | ||
| 559 | SetupCachedFramebuffer(fbkey, current_state); | 503 | current_state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(fbkey); |
| 560 | SyncViewport(current_state); | 504 | SyncViewport(current_state); |
| 561 | 505 | ||
| 562 | return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable}; | 506 | return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable}; |
| @@ -638,6 +582,7 @@ void RasterizerOpenGL::Clear() { | |||
| 638 | clear_state.ApplyDepth(); | 582 | clear_state.ApplyDepth(); |
| 639 | clear_state.ApplyStencilTest(); | 583 | clear_state.ApplyStencilTest(); |
| 640 | clear_state.ApplyViewport(); | 584 | clear_state.ApplyViewport(); |
| 585 | clear_state.ApplyFramebufferState(); | ||
| 641 | 586 | ||
| 642 | if (use_color) { | 587 | if (use_color) { |
| 643 | glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color); | 588 | glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index be5ac1b9f..2f13d9758 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include "video_core/rasterizer_interface.h" | 23 | #include "video_core/rasterizer_interface.h" |
| 24 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 24 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| 25 | #include "video_core/renderer_opengl/gl_device.h" | 25 | #include "video_core/renderer_opengl/gl_device.h" |
| 26 | #include "video_core/renderer_opengl/gl_framebuffer_cache.h" | ||
| 26 | #include "video_core/renderer_opengl/gl_global_cache.h" | 27 | #include "video_core/renderer_opengl/gl_global_cache.h" |
| 27 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 28 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 28 | #include "video_core/renderer_opengl/gl_sampler_cache.h" | 29 | #include "video_core/renderer_opengl/gl_sampler_cache.h" |
| @@ -49,7 +50,6 @@ namespace OpenGL { | |||
| 49 | 50 | ||
| 50 | struct ScreenInfo; | 51 | struct ScreenInfo; |
| 51 | struct DrawParameters; | 52 | struct DrawParameters; |
| 52 | struct FramebufferCacheKey; | ||
| 53 | 53 | ||
| 54 | class RasterizerOpenGL : public VideoCore::RasterizerInterface { | 54 | class RasterizerOpenGL : public VideoCore::RasterizerInterface { |
| 55 | public: | 55 | public: |
| @@ -193,6 +193,7 @@ private: | |||
| 193 | ShaderCacheOpenGL shader_cache; | 193 | ShaderCacheOpenGL shader_cache; |
| 194 | GlobalRegionCacheOpenGL global_cache; | 194 | GlobalRegionCacheOpenGL global_cache; |
| 195 | SamplerCacheOpenGL sampler_cache; | 195 | SamplerCacheOpenGL sampler_cache; |
| 196 | FramebufferCacheOpenGL framebuffer_cache; | ||
| 196 | 197 | ||
| 197 | Core::System& system; | 198 | Core::System& system; |
| 198 | ScreenInfo& screen_info; | 199 | ScreenInfo& screen_info; |
| @@ -203,7 +204,6 @@ private: | |||
| 203 | OGLVertexArray> | 204 | OGLVertexArray> |
| 204 | vertex_array_cache; | 205 | vertex_array_cache; |
| 205 | 206 | ||
| 206 | std::map<FramebufferCacheKey, OGLFramebuffer> framebuffer_cache; | ||
| 207 | FramebufferConfigState current_framebuffer_config_state; | 207 | FramebufferConfigState current_framebuffer_config_state; |
| 208 | std::pair<bool, bool> current_depth_stencil_usage{}; | 208 | std::pair<bool, bool> current_depth_stencil_usage{}; |
| 209 | 209 | ||
| @@ -226,8 +226,6 @@ private: | |||
| 226 | 226 | ||
| 227 | void SetupShaders(GLenum primitive_mode); | 227 | void SetupShaders(GLenum primitive_mode); |
| 228 | 228 | ||
| 229 | void SetupCachedFramebuffer(const FramebufferCacheKey& fbkey, OpenGLState& current_state); | ||
| 230 | |||
| 231 | enum class AccelDraw { Disabled, Arrays, Indexed }; | 229 | enum class AccelDraw { Disabled, Arrays, Indexed }; |
| 232 | AccelDraw accelerate_draw = AccelDraw::Disabled; | 230 | AccelDraw accelerate_draw = AccelDraw::Disabled; |
| 233 | 231 | ||
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 7058399e2..419c0de5e 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -133,7 +133,7 @@ public: | |||
| 133 | return {}; | 133 | return {}; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | if (regs.color_mask[index].raw != 0) { | 136 | if (regs.color_mask[index].raw == 0) { |
| 137 | SetEmptyColorBuffer(index); | 137 | SetEmptyColorBuffer(index); |
| 138 | return {}; | 138 | return {}; |
| 139 | } | 139 | } |