summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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 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
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) {
@@ -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
381void 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
364std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { 419std::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
41struct ScreenInfo; 41struct ScreenInfo;
42struct DrawParameters; 42struct DrawParameters;
43struct FramebufferCacheKey;
43 44
44class RasterizerOpenGL : public VideoCore::RasterizerInterface { 45class RasterizerOpenGL : public VideoCore::RasterizerInterface {
45public: 46public:
@@ -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