summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2018-11-18 22:20:26 -0300
committerGravatar ReinUsesLisp2018-11-29 16:34:46 -0300
commit1a2bb596db65580315f1447765b2a2638ae1aca8 (patch)
tree65b416461dcf94e79561579cf0c1dadebc9b6a4a
parentMerge pull request #1768 from greggameplayer/patch-2 (diff)
downloadyuzu-1a2bb596db65580315f1447765b2a2638ae1aca8.tar.gz
yuzu-1a2bb596db65580315f1447765b2a2638ae1aca8.tar.xz
yuzu-1a2bb596db65580315f1447765b2a2638ae1aca8.zip
gl_rasterizer: Implement a framebuffer cache
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp116
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h6
2 files changed, 82 insertions, 40 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a44bbfae8..7b836cc94 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -79,6 +79,26 @@ struct DrawParameters {
79 } 79 }
80}; 80};
81 81
82struct FramebufferCacheKey {
83 bool is_single_buffer = false;
84 bool stencil_enable = false;
85
86 std::array<GLenum, Maxwell::NumRenderTargets> color_attachments{};
87 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors{};
88 u32 colors_count = 0;
89
90 GLuint zeta = 0;
91
92 auto Tie() const {
93 return std::tie(is_single_buffer, stencil_enable, color_attachments, colors, colors_count,
94 zeta);
95 }
96
97 bool operator<(const FramebufferCacheKey& rhs) const {
98 return Tie() < rhs.Tie();
99 }
100};
101
82RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo& info) 102RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo& info)
83 : res_cache{*this}, shader_cache{*this}, emu_window{window}, screen_info{info}, 103 : res_cache{*this}, shader_cache{*this}, emu_window{window}, screen_info{info},
84 buffer_cache(*this, STREAM_BUFFER_SIZE) { 104 buffer_cache(*this, STREAM_BUFFER_SIZE) {
@@ -103,9 +123,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
103 123
104 OpenGLState::ApplyDefaultState(); 124 OpenGLState::ApplyDefaultState();
105 125
106 // Create render framebuffer
107 framebuffer.Create();
108
109 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 126 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
110 state.draw.shader_program = 0; 127 state.draw.shader_program = 0;
111 state.Apply(); 128 state.Apply();
@@ -363,6 +380,44 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
363 } 380 }
364} 381}
365 382
383void RasterizerOpenGL::SetupCachedFramebuffer(const FramebufferCacheKey& fbkey,
384 OpenGLState& current_state) {
385 const auto [entry, is_cache_miss] = framebuffer_cache.try_emplace(fbkey);
386 auto& framebuffer = entry->second;
387
388 if (is_cache_miss)
389 framebuffer.Create();
390
391 current_state.draw.draw_framebuffer = framebuffer.handle;
392 current_state.ApplyFramebufferState();
393
394 if (!is_cache_miss)
395 return;
396
397 if (fbkey.is_single_buffer) {
398 if (fbkey.color_attachments[0] != GL_NONE) {
399 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, fbkey.color_attachments[0], fbkey.colors[0],
400 0);
401 }
402 glDrawBuffer(fbkey.color_attachments[0]);
403 } else {
404 for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
405 if (fbkey.colors[index]) {
406 glFramebufferTexture(GL_DRAW_FRAMEBUFFER,
407 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
408 fbkey.colors[index], 0);
409 }
410 }
411 glDrawBuffers(fbkey.colors_count, fbkey.color_attachments.data());
412 }
413
414 if (fbkey.zeta) {
415 GLenum zeta_attachment =
416 fbkey.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
417 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, zeta_attachment, fbkey.zeta, 0);
418 }
419}
420
366std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { 421std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
367 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 422 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
368 423
@@ -446,10 +501,10 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
446 ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented"); 501 ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented");
447 502
448 // Bind the framebuffer surfaces 503 // Bind the framebuffer surfaces
449 current_state.draw.draw_framebuffer = framebuffer.handle;
450 current_state.ApplyFramebufferState();
451 current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0; 504 current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;
452 505
506 FramebufferCacheKey fbkey;
507
453 if (using_color_fb) { 508 if (using_color_fb) {
454 if (single_color_target) { 509 if (single_color_target) {
455 // Used when just a single color attachment is enabled, e.g. for clearing a color buffer 510 // Used when just a single color attachment is enabled, e.g. for clearing a color buffer
@@ -465,14 +520,12 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
465 state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion; 520 state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion;
466 } 521 }
467 522
468 glFramebufferTexture2D( 523 fbkey.is_single_buffer = true;
469 GL_DRAW_FRAMEBUFFER, 524 fbkey.color_attachments[0] =
470 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target), GL_TEXTURE_2D, 525 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target);
471 color_surface != nullptr ? color_surface->Texture().handle : 0, 0); 526 fbkey.colors[0] = color_surface != nullptr ? color_surface->Texture().handle : 0;
472 glDrawBuffer(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target));
473 } else { 527 } else {
474 // Multiple color attachments are enabled 528 // Multiple color attachments are enabled
475 std::array<GLenum, Maxwell::NumRenderTargets> buffers;
476 for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { 529 for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
477 Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents); 530 Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents);
478 531
@@ -487,22 +540,17 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
487 color_surface->GetSurfaceParams().srgb_conversion; 540 color_surface->GetSurfaceParams().srgb_conversion;
488 } 541 }
489 542
490 buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); 543 fbkey.color_attachments[index] =
491 glFramebufferTexture2D( 544 GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
492 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), 545 fbkey.colors[index] =
493 GL_TEXTURE_2D, color_surface != nullptr ? color_surface->Texture().handle : 0, 546 color_surface != nullptr ? color_surface->Texture().handle : 0;
494 0);
495 } 547 }
496 glDrawBuffers(regs.rt_control.count, buffers.data()); 548 fbkey.is_single_buffer = false;
549 fbkey.colors_count = regs.rt_control.count;
497 } 550 }
498 } else { 551 } else {
499 // No color attachments are enabled - zero out all of them 552 // No color attachments are enabled - leave them as zero
500 for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { 553 fbkey.is_single_buffer = true;
501 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
502 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), GL_TEXTURE_2D,
503 0, 0);
504 }
505 glDrawBuffer(GL_NONE);
506 } 554 }
507 555
508 if (depth_surface) { 556 if (depth_surface) {
@@ -510,22 +558,12 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
510 // the shader doesn't actually write to it. 558 // the shader doesn't actually write to it.
511 depth_surface->MarkAsModified(true, res_cache); 559 depth_surface->MarkAsModified(true, res_cache);
512 560
513 if (regs.stencil_enable) { 561 fbkey.zeta = depth_surface->Texture().handle;
514 // Attach both depth and stencil 562 fbkey.stencil_enable = regs.stencil_enable;
515 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
516 depth_surface->Texture().handle, 0);
517 } else {
518 // Attach depth
519 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
520 depth_surface->Texture().handle, 0);
521 // Clear stencil attachment
522 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
523 }
524 } else {
525 // Clear both depth and stencil attachment
526 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
527 0);
528 } 563 }
564
565 SetupCachedFramebuffer(fbkey, current_state);
566
529 SyncViewport(current_state); 567 SyncViewport(current_state);
530} 568}
531 569
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 7ec9746b1..959e8df63 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -40,6 +40,7 @@ namespace OpenGL {
40 40
41struct ScreenInfo; 41struct ScreenInfo;
42struct DrawParameters; 42struct DrawParameters;
43struct FramebufferCacheKey;
43 44
44class RasterizerOpenGL : public VideoCore::RasterizerInterface { 45class RasterizerOpenGL : public VideoCore::RasterizerInterface {
45public: 46public:
@@ -211,11 +212,12 @@ private:
211 OGLVertexArray> 212 OGLVertexArray>
212 vertex_array_cache; 213 vertex_array_cache;
213 214
215 std::map<FramebufferCacheKey, OGLFramebuffer> framebuffer_cache;
216
214 std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers; 217 std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers;
215 218
216 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; 219 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
217 OGLBufferCache buffer_cache; 220 OGLBufferCache buffer_cache;
218 OGLFramebuffer framebuffer;
219 PrimitiveAssembler primitive_assembler{buffer_cache}; 221 PrimitiveAssembler primitive_assembler{buffer_cache};
220 GLint uniform_buffer_alignment; 222 GLint uniform_buffer_alignment;
221 223
@@ -230,6 +232,8 @@ private:
230 232
231 void SetupShaders(GLenum primitive_mode); 233 void SetupShaders(GLenum primitive_mode);
232 234
235 void SetupCachedFramebuffer(const FramebufferCacheKey& fbkey, OpenGLState& current_state);
236
233 enum class AccelDraw { Disabled, Arrays, Indexed }; 237 enum class AccelDraw { Disabled, Arrays, Indexed };
234 AccelDraw accelerate_draw = AccelDraw::Disabled; 238 AccelDraw accelerate_draw = AccelDraw::Disabled;
235 239