diff options
Diffstat (limited to 'src')
| -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 9e93bd609..2b29fc45f 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) { |
| @@ -90,9 +110,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo | |||
| 90 | 110 | ||
| 91 | OpenGLState::ApplyDefaultState(); | 111 | OpenGLState::ApplyDefaultState(); |
| 92 | 112 | ||
| 93 | // Create render framebuffer | ||
| 94 | framebuffer.Create(); | ||
| 95 | |||
| 96 | shader_program_manager = std::make_unique<GLShader::ProgramManager>(); | 113 | shader_program_manager = std::make_unique<GLShader::ProgramManager>(); |
| 97 | state.draw.shader_program = 0; | 114 | state.draw.shader_program = 0; |
| 98 | state.Apply(); | 115 | state.Apply(); |
| @@ -361,6 +378,44 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 361 | SyncClipEnabled(clip_distances); | 378 | SyncClipEnabled(clip_distances); |
| 362 | } | 379 | } |
| 363 | 380 | ||
| 381 | void RasterizerOpenGL::SetupCachedFramebuffer(const FramebufferCacheKey& fbkey, | ||
| 382 | OpenGLState& current_state) { | ||
| 383 | const auto [entry, is_cache_miss] = framebuffer_cache.try_emplace(fbkey); | ||
| 384 | auto& framebuffer = entry->second; | ||
| 385 | |||
| 386 | if (is_cache_miss) | ||
| 387 | framebuffer.Create(); | ||
| 388 | |||
| 389 | current_state.draw.draw_framebuffer = framebuffer.handle; | ||
| 390 | current_state.ApplyFramebufferState(); | ||
| 391 | |||
| 392 | if (!is_cache_miss) | ||
| 393 | return; | ||
| 394 | |||
| 395 | if (fbkey.is_single_buffer) { | ||
| 396 | if (fbkey.color_attachments[0] != GL_NONE) { | ||
| 397 | glFramebufferTexture(GL_DRAW_FRAMEBUFFER, fbkey.color_attachments[0], fbkey.colors[0], | ||
| 398 | 0); | ||
| 399 | } | ||
| 400 | glDrawBuffer(fbkey.color_attachments[0]); | ||
| 401 | } else { | ||
| 402 | for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { | ||
| 403 | if (fbkey.colors[index]) { | ||
| 404 | glFramebufferTexture(GL_DRAW_FRAMEBUFFER, | ||
| 405 | GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), | ||
| 406 | fbkey.colors[index], 0); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | glDrawBuffers(fbkey.colors_count, fbkey.color_attachments.data()); | ||
| 410 | } | ||
| 411 | |||
| 412 | if (fbkey.zeta) { | ||
| 413 | GLenum zeta_attachment = | ||
| 414 | fbkey.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; | ||
| 415 | glFramebufferTexture(GL_DRAW_FRAMEBUFFER, zeta_attachment, fbkey.zeta, 0); | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 364 | std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { | 419 | std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { |
| 365 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 420 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; |
| 366 | 421 | ||
| @@ -444,10 +499,10 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us | |||
| 444 | UNIMPLEMENTED_IF(regs.rt_separate_frag_data != 0); | 499 | UNIMPLEMENTED_IF(regs.rt_separate_frag_data != 0); |
| 445 | 500 | ||
| 446 | // Bind the framebuffer surfaces | 501 | // Bind the framebuffer surfaces |
| 447 | current_state.draw.draw_framebuffer = framebuffer.handle; | ||
| 448 | current_state.ApplyFramebufferState(); | ||
| 449 | current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0; | 502 | current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0; |
| 450 | 503 | ||
| 504 | FramebufferCacheKey fbkey; | ||
| 505 | |||
| 451 | if (using_color_fb) { | 506 | if (using_color_fb) { |
| 452 | if (single_color_target) { | 507 | if (single_color_target) { |
| 453 | // Used when just a single color attachment is enabled, e.g. for clearing a color buffer | 508 | // Used when just a single color attachment is enabled, e.g. for clearing a color buffer |
| @@ -463,14 +518,12 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us | |||
| 463 | state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion; | 518 | state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion; |
| 464 | } | 519 | } |
| 465 | 520 | ||
| 466 | glFramebufferTexture2D( | 521 | fbkey.is_single_buffer = true; |
| 467 | GL_DRAW_FRAMEBUFFER, | 522 | fbkey.color_attachments[0] = |
| 468 | GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target), GL_TEXTURE_2D, | 523 | GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target); |
| 469 | color_surface != nullptr ? color_surface->Texture().handle : 0, 0); | 524 | fbkey.colors[0] = color_surface != nullptr ? color_surface->Texture().handle : 0; |
| 470 | glDrawBuffer(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target)); | ||
| 471 | } else { | 525 | } else { |
| 472 | // Multiple color attachments are enabled | 526 | // Multiple color attachments are enabled |
| 473 | std::array<GLenum, Maxwell::NumRenderTargets> buffers; | ||
| 474 | for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { | 527 | for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { |
| 475 | Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents); | 528 | Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents); |
| 476 | 529 | ||
| @@ -485,22 +538,17 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us | |||
| 485 | color_surface->GetSurfaceParams().srgb_conversion; | 538 | color_surface->GetSurfaceParams().srgb_conversion; |
| 486 | } | 539 | } |
| 487 | 540 | ||
| 488 | buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); | 541 | fbkey.color_attachments[index] = |
| 489 | glFramebufferTexture2D( | 542 | GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); |
| 490 | GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), | 543 | fbkey.colors[index] = |
| 491 | GL_TEXTURE_2D, color_surface != nullptr ? color_surface->Texture().handle : 0, | 544 | color_surface != nullptr ? color_surface->Texture().handle : 0; |
| 492 | 0); | ||
| 493 | } | 545 | } |
| 494 | glDrawBuffers(regs.rt_control.count, buffers.data()); | 546 | fbkey.is_single_buffer = false; |
| 547 | fbkey.colors_count = regs.rt_control.count; | ||
| 495 | } | 548 | } |
| 496 | } else { | 549 | } else { |
| 497 | // No color attachments are enabled - zero out all of them | 550 | // No color attachments are enabled - leave them as zero |
| 498 | for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { | 551 | fbkey.is_single_buffer = true; |
| 499 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, | ||
| 500 | GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), GL_TEXTURE_2D, | ||
| 501 | 0, 0); | ||
| 502 | } | ||
| 503 | glDrawBuffer(GL_NONE); | ||
| 504 | } | 552 | } |
| 505 | 553 | ||
| 506 | if (depth_surface) { | 554 | if (depth_surface) { |
| @@ -508,22 +556,12 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us | |||
| 508 | // the shader doesn't actually write to it. | 556 | // the shader doesn't actually write to it. |
| 509 | depth_surface->MarkAsModified(true, res_cache); | 557 | depth_surface->MarkAsModified(true, res_cache); |
| 510 | 558 | ||
| 511 | if (regs.stencil_enable) { | 559 | fbkey.zeta = depth_surface->Texture().handle; |
| 512 | // Attach both depth and stencil | 560 | fbkey.stencil_enable = regs.stencil_enable; |
| 513 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 514 | depth_surface->Texture().handle, 0); | ||
| 515 | } else { | ||
| 516 | // Attach depth | ||
| 517 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, | ||
| 518 | depth_surface->Texture().handle, 0); | ||
| 519 | // Clear stencil attachment | ||
| 520 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 521 | } | ||
| 522 | } else { | ||
| 523 | // Clear both depth and stencil attachment | ||
| 524 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||
| 525 | 0); | ||
| 526 | } | 561 | } |
| 562 | |||
| 563 | SetupCachedFramebuffer(fbkey, current_state); | ||
| 564 | |||
| 527 | SyncViewport(current_state); | 565 | SyncViewport(current_state); |
| 528 | } | 566 | } |
| 529 | 567 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 988fa3e27..8a891ffc7 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: |
| @@ -195,11 +196,12 @@ private: | |||
| 195 | OGLVertexArray> | 196 | OGLVertexArray> |
| 196 | vertex_array_cache; | 197 | vertex_array_cache; |
| 197 | 198 | ||
| 199 | std::map<FramebufferCacheKey, OGLFramebuffer> framebuffer_cache; | ||
| 200 | |||
| 198 | std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers; | 201 | std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers; |
| 199 | 202 | ||
| 200 | static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; | 203 | static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; |
| 201 | OGLBufferCache buffer_cache; | 204 | OGLBufferCache buffer_cache; |
| 202 | OGLFramebuffer framebuffer; | ||
| 203 | PrimitiveAssembler primitive_assembler{buffer_cache}; | 205 | PrimitiveAssembler primitive_assembler{buffer_cache}; |
| 204 | GLint uniform_buffer_alignment; | 206 | GLint uniform_buffer_alignment; |
| 205 | 207 | ||
| @@ -214,6 +216,8 @@ private: | |||
| 214 | 216 | ||
| 215 | void SetupShaders(GLenum primitive_mode); | 217 | void SetupShaders(GLenum primitive_mode); |
| 216 | 218 | ||
| 219 | void SetupCachedFramebuffer(const FramebufferCacheKey& fbkey, OpenGLState& current_state); | ||
| 220 | |||
| 217 | enum class AccelDraw { Disabled, Arrays, Indexed }; | 221 | enum class AccelDraw { Disabled, Arrays, Indexed }; |
| 218 | AccelDraw accelerate_draw = AccelDraw::Disabled; | 222 | AccelDraw accelerate_draw = AccelDraw::Disabled; |
| 219 | 223 | ||