summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-09-10 00:36:13 -0400
committerGravatar bunnei2018-09-10 00:41:20 -0400
commit035e6bd4071bbe9f986006695e5b0fff8eaedeef (patch)
tree9d13e4c9cd83ad646179f9c10d62bb7afa17f8e3
parentMerge pull request #1281 from bunnei/multi-rt (diff)
downloadyuzu-035e6bd4071bbe9f986006695e5b0fff8eaedeef.tar.gz
yuzu-035e6bd4071bbe9f986006695e5b0fff8eaedeef.tar.xz
yuzu-035e6bd4071bbe9f986006695e5b0fff8eaedeef.zip
gl_rasterizer: Implement clear for non-zero render targets.
- Several misc. changes to ConfigureFramebuffers in support of this.
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp103
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h13
2 files changed, 66 insertions, 50 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index c7e2c877c..d37863a00 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -294,19 +294,12 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
294 cached_pages.add({pages_interval, delta}); 294 cached_pages.add({pages_interval, delta});
295} 295}
296 296
297void RasterizerOpenGL::ConfigureFramebuffers(bool using_depth_fb, bool preserve_contents) { 297void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb,
298 bool preserve_contents,
299 boost::optional<size_t> single_color_target) {
298 MICROPROFILE_SCOPE(OpenGL_Framebuffer); 300 MICROPROFILE_SCOPE(OpenGL_Framebuffer);
299 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 301 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
300 302
301 const bool has_stencil = regs.stencil_enable;
302 const bool write_color_fb =
303 state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
304 state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE;
305
306 const bool write_depth_fb =
307 (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
308 (has_stencil && (state.stencil.front.write_mask || state.stencil.back.write_mask));
309
310 Surface depth_surface; 303 Surface depth_surface;
311 if (using_depth_fb) { 304 if (using_depth_fb) {
312 depth_surface = res_cache.GetDepthBufferSurface(preserve_contents); 305 depth_surface = res_cache.GetDepthBufferSurface(preserve_contents);
@@ -321,19 +314,41 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_depth_fb, bool preserve_
321 state.draw.draw_framebuffer = framebuffer.handle; 314 state.draw.draw_framebuffer = framebuffer.handle;
322 state.Apply(); 315 state.Apply();
323 316
324 std::array<GLenum, Maxwell::NumRenderTargets> buffers; 317 if (using_color_fb) {
325 for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { 318 if (single_color_target) {
326 Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents); 319 // Used when just a single color attachment is enabled, e.g. for clearing a color buffer
327 buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); 320 Surface color_surface =
328 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, 321 res_cache.GetColorBufferSurface(*single_color_target, preserve_contents);
329 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), GL_TEXTURE_2D, 322 glFramebufferTexture2D(
330 color_surface != nullptr ? color_surface->Texture().handle : 0, 0); 323 GL_DRAW_FRAMEBUFFER,
324 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target), GL_TEXTURE_2D,
325 color_surface != nullptr ? color_surface->Texture().handle : 0, 0);
326 glDrawBuffer(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target));
327 } else {
328 // Multiple color attachments are enabled
329 std::array<GLenum, Maxwell::NumRenderTargets> buffers;
330 for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
331 Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents);
332 buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
333 glFramebufferTexture2D(
334 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
335 GL_TEXTURE_2D, color_surface != nullptr ? color_surface->Texture().handle : 0,
336 0);
337 }
338 glDrawBuffers(regs.rt_control.count, buffers.data());
339 }
340 } else {
341 // No color attachments are enabled - zero out all of them
342 for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
343 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
344 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), GL_TEXTURE_2D,
345 0, 0);
346 }
347 glDrawBuffer(GL_NONE);
331 } 348 }
332 349
333 glDrawBuffers(regs.rt_control.count, buffers.data());
334
335 if (depth_surface) { 350 if (depth_surface) {
336 if (has_stencil) { 351 if (regs.stencil_enable) {
337 // Attach both depth and stencil 352 // Attach both depth and stencil
338 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 353 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
339 depth_surface->Texture().handle, 0); 354 depth_surface->Texture().handle, 0);
@@ -360,8 +375,9 @@ void RasterizerOpenGL::Clear() {
360 SCOPE_EXIT({ prev_state.Apply(); }); 375 SCOPE_EXIT({ prev_state.Apply(); });
361 376
362 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 377 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
363 bool use_color_fb = false; 378 bool use_color{};
364 bool use_depth_fb = false; 379 bool use_depth{};
380 bool use_stencil{};
365 381
366 OpenGLState clear_state; 382 OpenGLState clear_state;
367 clear_state.draw.draw_framebuffer = state.draw.draw_framebuffer; 383 clear_state.draw.draw_framebuffer = state.draw.draw_framebuffer;
@@ -370,22 +386,13 @@ void RasterizerOpenGL::Clear() {
370 clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE; 386 clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
371 clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE; 387 clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
372 388
373 GLbitfield clear_mask{};
374 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || 389 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
375 regs.clear_buffers.A) { 390 regs.clear_buffers.A) {
376 if (regs.clear_buffers.RT == 0) { 391 use_color = true;
377 // We only support clearing the first color attachment for now
378 clear_mask |= GL_COLOR_BUFFER_BIT;
379 use_color_fb = true;
380 } else {
381 // TODO(subv): Add support for the other color attachments
382 LOG_CRITICAL(HW_GPU, "Clear unimplemented for RT {}", regs.clear_buffers.RT);
383 }
384 } 392 }
385 if (regs.clear_buffers.Z) { 393 if (regs.clear_buffers.Z) {
386 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!"); 394 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
387 use_depth_fb = true; 395 use_depth = true;
388 clear_mask |= GL_DEPTH_BUFFER_BIT;
389 396
390 // Always enable the depth write when clearing the depth buffer. The depth write mask is 397 // Always enable the depth write when clearing the depth buffer. The depth write mask is
391 // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. 398 // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true.
@@ -394,33 +401,33 @@ void RasterizerOpenGL::Clear() {
394 } 401 }
395 if (regs.clear_buffers.S) { 402 if (regs.clear_buffers.S) {
396 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!"); 403 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!");
397 use_depth_fb = true; 404 use_stencil = true;
398 clear_mask |= GL_STENCIL_BUFFER_BIT;
399 clear_state.stencil.test_enabled = true; 405 clear_state.stencil.test_enabled = true;
400 } 406 }
401 407
402 if (!use_color_fb && !use_depth_fb) { 408 if (!use_color && !use_depth && !use_stencil) {
403 // No color surface nor depth/stencil surface are enabled 409 // No color surface nor depth/stencil surface are enabled
404 return; 410 return;
405 } 411 }
406 412
407 if (clear_mask == 0) {
408 // No clear mask is enabled
409 return;
410 }
411
412 ScopeAcquireGLContext acquire_context{emu_window}; 413 ScopeAcquireGLContext acquire_context{emu_window};
413 414
414 ConfigureFramebuffers(use_depth_fb, false); 415 ConfigureFramebuffers(use_color, use_depth || use_stencil, false,
416 regs.clear_buffers.RT.Value());
415 417
416 clear_state.Apply(); 418 clear_state.Apply();
417 419
418 glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2], 420 if (use_color) {
419 regs.clear_color[3]); 421 glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color);
420 glClearDepth(regs.clear_depth); 422 }
421 glClearStencil(regs.clear_stencil);
422 423
423 glClear(clear_mask); 424 if (use_depth && use_stencil) {
425 glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
426 } else if (use_depth) {
427 glClearBufferfv(GL_DEPTH, 0, &regs.clear_depth);
428 } else if (use_stencil) {
429 glClearBufferiv(GL_STENCIL, 0, &regs.clear_stencil);
430 }
424} 431}
425 432
426void RasterizerOpenGL::DrawArrays() { 433void RasterizerOpenGL::DrawArrays() {
@@ -433,7 +440,7 @@ void RasterizerOpenGL::DrawArrays() {
433 440
434 ScopeAcquireGLContext acquire_context{emu_window}; 441 ScopeAcquireGLContext acquire_context{emu_window};
435 442
436 ConfigureFramebuffers(true, true); 443 ConfigureFramebuffers();
437 444
438 SyncDepthTestState(); 445 SyncDepthTestState();
439 SyncStencilTestState(); 446 SyncStencilTestState();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 3d62cc196..a39f9cdf6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -13,6 +13,7 @@
13#include <vector> 13#include <vector>
14 14
15#include <boost/icl/interval_map.hpp> 15#include <boost/icl/interval_map.hpp>
16#include <boost/optional.hpp>
16#include <boost/range/iterator_range.hpp> 17#include <boost/range/iterator_range.hpp>
17#include <glad/glad.h> 18#include <glad/glad.h>
18 19
@@ -97,8 +98,16 @@ private:
97 GLvec4 border_color; 98 GLvec4 border_color;
98 }; 99 };
99 100
100 /// Configures the color and depth framebuffer states 101 /**
101 void ConfigureFramebuffers(bool using_depth_fb, bool preserve_contents); 102 * Configures the color and depth framebuffer states.
103 * @param use_color_fb If true, configure color framebuffers.
104 * @param using_depth_fb If true, configure the depth/stencil framebuffer.
105 * @param preserve_contents If true, tries to preserve data from a previously used framebuffer.
106 * @param single_color_target Specifies if a single color buffer target should be used.
107 */
108 void ConfigureFramebuffers(bool use_color_fb = true, bool using_depth_fb = true,
109 bool preserve_contents = true,
110 boost::optional<size_t> single_color_target = {});
102 111
103 /* 112 /*
104 * Configures the current constbuffers to use for the draw command. 113 * Configures the current constbuffers to use for the draw command.