summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-05-11 03:15:49 -0300
committerGravatar ReinUsesLisp2019-06-20 21:36:12 -0300
commit9098905dd13bb68f2fe49a9590688b76cc999fdd (patch)
tree496c5711a40b37341765aedba0aebb458748beea /src
parenttexture_cache return invalid buffer on deactivated color_mask (diff)
downloadyuzu-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.txt2
-rw-r--r--src/video_core/renderer_opengl/gl_framebuffer_cache.cpp73
-rw-r--r--src/video_core/renderer_opengl/gl_framebuffer_cache.h68
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp59
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h6
-rw-r--r--src/video_core/texture_cache/texture_cache.h2
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
13namespace OpenGL {
14
15using Maxwell = Tegra::Engines::Maxwell3D::Regs;
16
17FramebufferCacheOpenGL::FramebufferCacheOpenGL() = default;
18
19FramebufferCacheOpenGL::~FramebufferCacheOpenGL() = default;
20
21GLuint 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
30OGLFramebuffer 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
61std::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
67bool 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
19namespace OpenGL {
20
21struct 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
41namespace std {
42
43template <>
44struct 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
52namespace OpenGL {
53
54class FramebufferCacheOpenGL {
55public:
56 FramebufferCacheOpenGL();
57 ~FramebufferCacheOpenGL();
58
59 GLuint GetFramebuffer(const FramebufferCacheKey& key);
60
61private:
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
81struct 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
101RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, 81RasterizerOpenGL::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
358void 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
394std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { 338std::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
50struct ScreenInfo; 51struct ScreenInfo;
51struct DrawParameters; 52struct DrawParameters;
52struct FramebufferCacheKey;
53 53
54class RasterizerOpenGL : public VideoCore::RasterizerInterface { 54class RasterizerOpenGL : public VideoCore::RasterizerInterface {
55public: 55public:
@@ -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 }