diff options
| author | 2018-11-18 22:20:26 -0300 | |
|---|---|---|
| committer | 2018-11-29 16:34:46 -0300 | |
| commit | 1a2bb596db65580315f1447765b2a2638ae1aca8 (patch) | |
| tree | 65b416461dcf94e79561579cf0c1dadebc9b6a4a | |
| parent | Merge pull request #1768 from greggameplayer/patch-2 (diff) | |
| download | yuzu-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.cpp | 116 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 6 |
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 | ||
| 82 | struct 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 | |||
| 82 | RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo& info) | 102 | RasterizerOpenGL::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 | ||
| 383 | void 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 | |||
| 366 | std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { | 421 | std::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 | ||
| 41 | struct ScreenInfo; | 41 | struct ScreenInfo; |
| 42 | struct DrawParameters; | 42 | struct DrawParameters; |
| 43 | struct FramebufferCacheKey; | ||
| 43 | 44 | ||
| 44 | class RasterizerOpenGL : public VideoCore::RasterizerInterface { | 45 | class RasterizerOpenGL : public VideoCore::RasterizerInterface { |
| 45 | public: | 46 | public: |
| @@ -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 | ||