summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2019-11-30 18:46:40 -0500
committerGravatar GitHub2019-11-30 18:46:40 -0500
commit930b7c18a6d73d2365c8c2b868279fe5d44630d3 (patch)
treefa68e3c531ec46b3aa5e1a525dc3bbbc5d784255 /src
parentMerge pull request #3185 from ReinUsesLisp/oob-texture (diff)
parentgl_framebuffer_cache: Optimize framebuffer key (diff)
downloadyuzu-930b7c18a6d73d2365c8c2b868279fe5d44630d3.tar.gz
yuzu-930b7c18a6d73d2365c8c2b868279fe5d44630d3.tar.xz
yuzu-930b7c18a6d73d2365c8c2b868279fe5d44630d3.zip
Merge pull request #3184 from ReinUsesLisp/framebuffer-cache
gl_framebuffer_cache: Optimize framebuffer cache management
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_framebuffer_cache.cpp57
-rw-r--r--src/video_core/renderer_opengl/gl_framebuffer_cache.h19
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp63
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h2
4 files changed, 69 insertions, 72 deletions
diff --git a/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp b/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp
index a5d69d78d..874ed3c6e 100644
--- a/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_framebuffer_cache.cpp
@@ -3,9 +3,12 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <tuple> 5#include <tuple>
6#include <unordered_map>
7#include <utility>
6 8
7#include "common/cityhash.h" 9#include <glad/glad.h>
8#include "common/scope_exit.h" 10
11#include "common/common_types.h"
9#include "video_core/engines/maxwell_3d.h" 12#include "video_core/engines/maxwell_3d.h"
10#include "video_core/renderer_opengl/gl_framebuffer_cache.h" 13#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
11#include "video_core/renderer_opengl/gl_state.h" 14#include "video_core/renderer_opengl/gl_state.h"
@@ -13,6 +16,7 @@
13namespace OpenGL { 16namespace OpenGL {
14 17
15using Maxwell = Tegra::Engines::Maxwell3D::Regs; 18using Maxwell = Tegra::Engines::Maxwell3D::Regs;
19using VideoCore::Surface::SurfaceType;
16 20
17FramebufferCacheOpenGL::FramebufferCacheOpenGL() = default; 21FramebufferCacheOpenGL::FramebufferCacheOpenGL() = default;
18 22
@@ -35,36 +39,49 @@ OGLFramebuffer FramebufferCacheOpenGL::CreateFramebuffer(const FramebufferCacheK
35 local_state.draw.draw_framebuffer = framebuffer.handle; 39 local_state.draw.draw_framebuffer = framebuffer.handle;
36 local_state.ApplyFramebufferState(); 40 local_state.ApplyFramebufferState();
37 41
42 if (key.zeta) {
43 const bool stencil = key.zeta->GetSurfaceParams().type == SurfaceType::DepthStencil;
44 const GLenum attach_target = stencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
45 key.zeta->Attach(attach_target, GL_DRAW_FRAMEBUFFER);
46 }
47
48 std::size_t num_buffers = 0;
49 std::array<GLenum, Maxwell::NumRenderTargets> targets;
50
38 for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { 51 for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
39 if (key.colors[index]) { 52 if (!key.colors[index]) {
40 key.colors[index]->Attach(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), 53 targets[index] = GL_NONE;
41 GL_DRAW_FRAMEBUFFER); 54 continue;
42 } 55 }
56 const GLenum attach_target = GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index);
57 key.colors[index]->Attach(attach_target, GL_DRAW_FRAMEBUFFER);
58
59 const u32 attachment = (key.color_attachments >> (BitsPerAttachment * index)) & 0b1111;
60 targets[index] = GL_COLOR_ATTACHMENT0 + attachment;
61 num_buffers = index + 1;
43 } 62 }
44 if (key.colors_count) { 63
45 glDrawBuffers(key.colors_count, key.color_attachments.data()); 64 if (num_buffers > 0) {
65 glDrawBuffers(static_cast<GLsizei>(num_buffers), std::data(targets));
46 } else { 66 } else {
47 glDrawBuffer(GL_NONE); 67 glDrawBuffer(GL_NONE);
48 } 68 }
49 69
50 if (key.zeta) {
51 key.zeta->Attach(key.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT,
52 GL_DRAW_FRAMEBUFFER);
53 }
54
55 return framebuffer; 70 return framebuffer;
56} 71}
57 72
58std::size_t FramebufferCacheKey::Hash() const { 73std::size_t FramebufferCacheKey::Hash() const noexcept {
59 static_assert(sizeof(*this) % sizeof(u64) == 0, "Unaligned struct"); 74 std::size_t hash = std::hash<View>{}(zeta);
60 return static_cast<std::size_t>( 75 for (const auto& color : colors) {
61 Common::CityHash64(reinterpret_cast<const char*>(this), sizeof(*this))); 76 hash ^= std::hash<View>{}(color);
77 }
78 hash ^= static_cast<std::size_t>(color_attachments) << 16;
79 return hash;
62} 80}
63 81
64bool FramebufferCacheKey::operator==(const FramebufferCacheKey& rhs) const { 82bool FramebufferCacheKey::operator==(const FramebufferCacheKey& rhs) const noexcept {
65 return std::tie(stencil_enable, colors_count, color_attachments, colors, zeta) == 83 return std::tie(colors, zeta, color_attachments) ==
66 std::tie(rhs.stencil_enable, rhs.colors_count, rhs.color_attachments, rhs.colors, 84 std::tie(rhs.colors, rhs.zeta, rhs.color_attachments);
67 rhs.zeta);
68} 85}
69 86
70} // namespace OpenGL 87} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_framebuffer_cache.h b/src/video_core/renderer_opengl/gl_framebuffer_cache.h
index 424344c48..02ec80ae9 100644
--- a/src/video_core/renderer_opengl/gl_framebuffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_framebuffer_cache.h
@@ -18,21 +18,24 @@
18 18
19namespace OpenGL { 19namespace OpenGL {
20 20
21struct alignas(sizeof(u64)) FramebufferCacheKey { 21constexpr std::size_t BitsPerAttachment = 4;
22 bool stencil_enable = false;
23 u16 colors_count = 0;
24 22
25 std::array<GLenum, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> color_attachments{}; 23struct FramebufferCacheKey {
26 std::array<View, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors;
27 View zeta; 24 View zeta;
25 std::array<View, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors;
26 u32 color_attachments = 0;
28 27
29 std::size_t Hash() const; 28 std::size_t Hash() const noexcept;
30 29
31 bool operator==(const FramebufferCacheKey& rhs) const; 30 bool operator==(const FramebufferCacheKey& rhs) const noexcept;
32 31
33 bool operator!=(const FramebufferCacheKey& rhs) const { 32 bool operator!=(const FramebufferCacheKey& rhs) const noexcept {
34 return !operator==(rhs); 33 return !operator==(rhs);
35 } 34 }
35
36 void SetAttachment(std::size_t index, u32 attachment) {
37 color_attachments |= attachment << (BitsPerAttachment * index);
38 }
36}; 39};
37 40
38} // namespace OpenGL 41} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a568a4343..9eef7fcd2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -93,7 +93,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
93 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 93 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
94 state.draw.shader_program = 0; 94 state.draw.shader_program = 0;
95 state.Apply(); 95 state.Apply();
96 clear_framebuffer.Create();
97 96
98 LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here"); 97 LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here");
99 CheckExtensions(); 98 CheckExtensions();
@@ -373,78 +372,58 @@ void RasterizerOpenGL::ConfigureFramebuffers() {
373 UNIMPLEMENTED_IF(regs.rt_separate_frag_data == 0); 372 UNIMPLEMENTED_IF(regs.rt_separate_frag_data == 0);
374 373
375 // Bind the framebuffer surfaces 374 // Bind the framebuffer surfaces
376 FramebufferCacheKey fbkey; 375 FramebufferCacheKey key;
377 for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { 376 const auto colors_count = static_cast<std::size_t>(regs.rt_control.count);
377 for (std::size_t index = 0; index < colors_count; ++index) {
378 View color_surface{texture_cache.GetColorBufferSurface(index, true)}; 378 View color_surface{texture_cache.GetColorBufferSurface(index, true)};
379 379 if (!color_surface) {
380 if (color_surface) { 380 continue;
381 // Assume that a surface will be written to if it is used as a framebuffer, even
382 // if the shader doesn't actually write to it.
383 texture_cache.MarkColorBufferInUse(index);
384 } 381 }
382 // Assume that a surface will be written to if it is used as a framebuffer, even
383 // if the shader doesn't actually write to it.
384 texture_cache.MarkColorBufferInUse(index);
385 385
386 fbkey.color_attachments[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); 386 key.SetAttachment(index, regs.rt_control.GetMap(index));
387 fbkey.colors[index] = std::move(color_surface); 387 key.colors[index] = std::move(color_surface);
388 } 388 }
389 fbkey.colors_count = static_cast<u16>(regs.rt_control.count);
390 389
391 if (depth_surface) { 390 if (depth_surface) {
392 // Assume that a surface will be written to if it is used as a framebuffer, even if 391 // Assume that a surface will be written to if it is used as a framebuffer, even if
393 // the shader doesn't actually write to it. 392 // the shader doesn't actually write to it.
394 texture_cache.MarkDepthBufferInUse(); 393 texture_cache.MarkDepthBufferInUse();
395 394 key.zeta = std::move(depth_surface);
396 fbkey.stencil_enable = depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil;
397 fbkey.zeta = std::move(depth_surface);
398 } 395 }
399 396
400 texture_cache.GuardRenderTargets(false); 397 texture_cache.GuardRenderTargets(false);
401 398
402 state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(fbkey); 399 state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(key);
403 SyncViewport(state); 400 SyncViewport(state);
404} 401}
405 402
406void RasterizerOpenGL::ConfigureClearFramebuffer(OpenGLState& current_state, bool using_color_fb, 403void RasterizerOpenGL::ConfigureClearFramebuffer(OpenGLState& current_state, bool using_color_fb,
407 bool using_depth_fb, bool using_stencil_fb) { 404 bool using_depth_fb, bool using_stencil_fb) {
405 using VideoCore::Surface::SurfaceType;
406
408 auto& gpu = system.GPU().Maxwell3D(); 407 auto& gpu = system.GPU().Maxwell3D();
409 const auto& regs = gpu.regs; 408 const auto& regs = gpu.regs;
410 409
411 texture_cache.GuardRenderTargets(true); 410 texture_cache.GuardRenderTargets(true);
412 View color_surface{}; 411 View color_surface;
413 if (using_color_fb) { 412 if (using_color_fb) {
414 color_surface = texture_cache.GetColorBufferSurface(regs.clear_buffers.RT, false); 413 color_surface = texture_cache.GetColorBufferSurface(regs.clear_buffers.RT, false);
415 } 414 }
416 View depth_surface{}; 415 View depth_surface;
417 if (using_depth_fb || using_stencil_fb) { 416 if (using_depth_fb || using_stencil_fb) {
418 depth_surface = texture_cache.GetDepthBufferSurface(false); 417 depth_surface = texture_cache.GetDepthBufferSurface(false);
419 } 418 }
420 texture_cache.GuardRenderTargets(false); 419 texture_cache.GuardRenderTargets(false);
421 420
422 current_state.draw.draw_framebuffer = clear_framebuffer.handle; 421 FramebufferCacheKey key;
423 current_state.ApplyFramebufferState(); 422 key.colors[0] = color_surface;
424 423 key.zeta = depth_surface;
425 if (color_surface) {
426 color_surface->Attach(GL_COLOR_ATTACHMENT0, GL_DRAW_FRAMEBUFFER);
427 } else {
428 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
429 }
430 424
431 if (depth_surface) { 425 current_state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(key);
432 const auto& params = depth_surface->GetSurfaceParams(); 426 current_state.ApplyFramebufferState();
433 switch (params.type) {
434 case VideoCore::Surface::SurfaceType::Depth:
435 depth_surface->Attach(GL_DEPTH_ATTACHMENT, GL_DRAW_FRAMEBUFFER);
436 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
437 break;
438 case VideoCore::Surface::SurfaceType::DepthStencil:
439 depth_surface->Attach(GL_DEPTH_STENCIL_ATTACHMENT, GL_DRAW_FRAMEBUFFER);
440 break;
441 default:
442 UNIMPLEMENTED();
443 }
444 } else {
445 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
446 0);
447 }
448} 427}
449 428
450void RasterizerOpenGL::Clear() { 429void RasterizerOpenGL::Clear() {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 0e47d71df..04c1ca551 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -223,8 +223,6 @@ private:
223 223
224 enum class AccelDraw { Disabled, Arrays, Indexed }; 224 enum class AccelDraw { Disabled, Arrays, Indexed };
225 AccelDraw accelerate_draw = AccelDraw::Disabled; 225 AccelDraw accelerate_draw = AccelDraw::Disabled;
226
227 OGLFramebuffer clear_framebuffer;
228}; 226};
229 227
230} // namespace OpenGL 228} // namespace OpenGL