summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-09-20 23:41:25 -0400
committerGravatar bunnei2018-09-30 14:31:58 -0400
commitf543b43fd054ae9ec1e4d693a9bd1540e408ddac (patch)
tree25ad751cf70c87c7e7ef7f9345bb680365eb8929 /src
parentgl_shader_decompiler: TEXS: Implement TextureType::TextureCube. (diff)
downloadyuzu-f543b43fd054ae9ec1e4d693a9bd1540e408ddac.tar.gz
yuzu-f543b43fd054ae9ec1e4d693a9bd1540e408ddac.tar.xz
yuzu-f543b43fd054ae9ec1e4d693a9bd1540e408ddac.zip
gl_rasterizer_cache: Implement render to cubemap.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp301
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h34
-rw-r--r--src/video_core/textures/texture.h2
3 files changed, 218 insertions, 119 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index bd4330327..8abbe0113 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -87,6 +87,9 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
87 87
88 params.size_in_bytes_total = params.SizeInBytesTotal(); 88 params.size_in_bytes_total = params.SizeInBytesTotal();
89 params.size_in_bytes_2d = params.SizeInBytes2D(); 89 params.size_in_bytes_2d = params.SizeInBytes2D();
90 params.max_mip_level = config.tic.max_mip_level + 1;
91 params.rt = {};
92
90 return params; 93 return params;
91} 94}
92 95
@@ -106,6 +109,14 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
106 params.depth = 1; 109 params.depth = 1;
107 params.size_in_bytes_total = params.SizeInBytesTotal(); 110 params.size_in_bytes_total = params.SizeInBytesTotal();
108 params.size_in_bytes_2d = params.SizeInBytes2D(); 111 params.size_in_bytes_2d = params.SizeInBytes2D();
112 params.max_mip_level = 0;
113
114 // Render target specific parameters, not used for caching
115 params.rt.index = static_cast<u32>(index);
116 params.rt.array_mode = config.array_mode;
117 params.rt.layer_stride = config.layer_stride;
118 params.rt.base_layer = config.base_layer;
119
109 return params; 120 return params;
110} 121}
111 122
@@ -126,6 +137,9 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
126 params.depth = 1; 137 params.depth = 1;
127 params.size_in_bytes_total = params.SizeInBytesTotal(); 138 params.size_in_bytes_total = params.SizeInBytesTotal();
128 params.size_in_bytes_2d = params.SizeInBytes2D(); 139 params.size_in_bytes_2d = params.SizeInBytes2D();
140 params.max_mip_level = 0;
141 params.rt = {};
142
129 return params; 143 return params;
130} 144}
131 145
@@ -418,7 +432,8 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, std::size_t, VAddr),
418}; 432};
419 433
420static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface, 434static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
421 GLuint read_fb_handle, GLuint draw_fb_handle, std::size_t face = 0) { 435 GLuint read_fb_handle, GLuint draw_fb_handle, GLenum src_attachment = 0,
436 GLenum dst_attachment = 0, std::size_t cubemap_face = 0) {
422 437
423 const auto& src_params{src_surface->GetSurfaceParams()}; 438 const auto& src_params{src_surface->GetSurfaceParams()};
424 const auto& dst_params{dst_surface->GetSurfaceParams()}; 439 const auto& dst_params{dst_surface->GetSurfaceParams()};
@@ -436,34 +451,35 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
436 if (src_params.type == SurfaceType::ColorTexture) { 451 if (src_params.type == SurfaceType::ColorTexture) {
437 switch (src_params.target) { 452 switch (src_params.target) {
438 case SurfaceParams::SurfaceTarget::Texture2D: 453 case SurfaceParams::SurfaceTarget::Texture2D:
439 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 454 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
440 src_surface->Texture().handle, 0); 455 GL_TEXTURE_2D, src_surface->Texture().handle, 0);
441 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 456 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
442 0, 0); 457 0, 0);
443 break; 458 break;
444 case SurfaceParams::SurfaceTarget::TextureCubemap: 459 case SurfaceParams::SurfaceTarget::TextureCubemap:
445 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 460 glFramebufferTexture2D(
446 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), 461 GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
447 src_surface->Texture().handle, 0); 462 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face),
448 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 463 src_surface->Texture().handle, 0);
449 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), 0, 464 glFramebufferTexture2D(
450 0); 465 GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
466 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0);
451 break; 467 break;
452 case SurfaceParams::SurfaceTarget::Texture2DArray: 468 case SurfaceParams::SurfaceTarget::Texture2DArray:
453 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 469 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
454 src_surface->Texture().handle, 0, 0); 470 src_surface->Texture().handle, 0, 0);
455 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0); 471 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0);
456 break; 472 break;
457 case SurfaceParams::SurfaceTarget::Texture3D: 473 case SurfaceParams::SurfaceTarget::Texture3D:
458 glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 474 glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
459 SurfaceTargetToGL(src_params.target), 475 SurfaceTargetToGL(src_params.target),
460 src_surface->Texture().handle, 0, 0); 476 src_surface->Texture().handle, 0, 0);
461 glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 477 glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
462 SurfaceTargetToGL(src_params.target), 0, 0, 0); 478 SurfaceTargetToGL(src_params.target), 0, 0, 0);
463 break; 479 break;
464 default: 480 default:
465 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 481 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
466 src_surface->Texture().handle, 0); 482 GL_TEXTURE_2D, src_surface->Texture().handle, 0);
467 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 483 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
468 0, 0); 484 0, 0);
469 break; 485 break;
@@ -471,35 +487,36 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
471 487
472 switch (dst_params.target) { 488 switch (dst_params.target) {
473 case SurfaceParams::SurfaceTarget::Texture2D: 489 case SurfaceParams::SurfaceTarget::Texture2D:
474 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 490 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
475 dst_surface->Texture().handle, 0); 491 GL_TEXTURE_2D, dst_surface->Texture().handle, 0);
476 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 492 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
477 0, 0); 493 0, 0);
478 break; 494 break;
479 case SurfaceParams::SurfaceTarget::TextureCubemap: 495 case SurfaceParams::SurfaceTarget::TextureCubemap:
480 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 496 glFramebufferTexture2D(
481 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), 497 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
482 dst_surface->Texture().handle, 0); 498 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face),
483 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 499 dst_surface->Texture().handle, 0);
484 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), 0, 500 glFramebufferTexture2D(
485 0); 501 GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
502 static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0);
486 break; 503 break;
487 case SurfaceParams::SurfaceTarget::Texture2DArray: 504 case SurfaceParams::SurfaceTarget::Texture2DArray:
488 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 505 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
489 dst_surface->Texture().handle, 0, 0); 506 dst_surface->Texture().handle, 0, 0);
490 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0); 507 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0);
491 break; 508 break;
492 509
493 case SurfaceParams::SurfaceTarget::Texture3D: 510 case SurfaceParams::SurfaceTarget::Texture3D:
494 glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 511 glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
495 SurfaceTargetToGL(dst_params.target), 512 SurfaceTargetToGL(dst_params.target),
496 dst_surface->Texture().handle, 0, 0); 513 dst_surface->Texture().handle, 0, 0);
497 glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 514 glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
498 SurfaceTargetToGL(dst_params.target), 0, 0, 0); 515 SurfaceTargetToGL(dst_params.target), 0, 0, 0);
499 break; 516 break;
500 default: 517 default:
501 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 518 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
502 dst_surface->Texture().handle, 0); 519 GL_TEXTURE_2D, dst_surface->Texture().handle, 0);
503 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 520 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
504 0, 0); 521 0, 0);
505 break; 522 break;
@@ -507,23 +524,27 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
507 524
508 buffers = GL_COLOR_BUFFER_BIT; 525 buffers = GL_COLOR_BUFFER_BIT;
509 } else if (src_params.type == SurfaceType::Depth) { 526 } else if (src_params.type == SurfaceType::Depth) {
510 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 527 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
528 GL_TEXTURE_2D, 0, 0);
511 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 529 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
512 src_surface->Texture().handle, 0); 530 src_surface->Texture().handle, 0);
513 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); 531 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
514 532
515 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 533 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
534 GL_TEXTURE_2D, 0, 0);
516 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 535 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
517 dst_surface->Texture().handle, 0); 536 dst_surface->Texture().handle, 0);
518 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); 537 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
519 538
520 buffers = GL_DEPTH_BUFFER_BIT; 539 buffers = GL_DEPTH_BUFFER_BIT;
521 } else if (src_params.type == SurfaceType::DepthStencil) { 540 } else if (src_params.type == SurfaceType::DepthStencil) {
522 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 541 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
542 GL_TEXTURE_2D, 0, 0);
523 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 543 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
524 src_surface->Texture().handle, 0); 544 src_surface->Texture().handle, 0);
525 545
526 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 546 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
547 GL_TEXTURE_2D, 0, 0);
527 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 548 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
528 dst_surface->Texture().handle, 0); 549 dst_surface->Texture().handle, 0);
529 550
@@ -538,6 +559,92 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
538 return true; 559 return true;
539} 560}
540 561
562static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
563 GLuint copy_pbo_handle, GLenum src_attachment = 0,
564 GLenum dst_attachment = 0, std::size_t cubemap_face = 0) {
565 ASSERT_MSG(dst_attachment == 0, "Unimplemented");
566
567 const auto& src_params{src_surface->GetSurfaceParams()};
568 const auto& dst_params{dst_surface->GetSurfaceParams()};
569
570 auto source_format = GetFormatTuple(src_params.pixel_format, src_params.component_type);
571 auto dest_format = GetFormatTuple(dst_params.pixel_format, dst_params.component_type);
572
573 std::size_t buffer_size =
574 std::max(src_params.size_in_bytes_total, dst_params.size_in_bytes_total);
575
576 glBindBuffer(GL_PIXEL_PACK_BUFFER, copy_pbo_handle);
577 glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
578 if (source_format.compressed) {
579 glGetCompressedTextureImage(src_surface->Texture().handle, src_attachment,
580 static_cast<GLsizei>(src_params.size_in_bytes_total), nullptr);
581 } else {
582 glGetTextureImage(src_surface->Texture().handle, src_attachment, source_format.format,
583 source_format.type, static_cast<GLsizei>(src_params.size_in_bytes_total),
584 nullptr);
585 }
586 // If the new texture is bigger than the previous one, we need to fill in the rest with data
587 // from the CPU.
588 if (src_params.size_in_bytes_total < dst_params.size_in_bytes_total) {
589 // Upload the rest of the memory.
590 if (dst_params.is_tiled) {
591 // TODO(Subv): We might have to de-tile the subtexture and re-tile it with the rest
592 // of the data in this case. Games like Super Mario Odyssey seem to hit this case
593 // when drawing, it re-uses the memory of a previous texture as a bigger framebuffer
594 // but it doesn't clear it beforehand, the texture is already full of zeros.
595 LOG_DEBUG(HW_GPU, "Trying to upload extra texture data from the CPU during "
596 "reinterpretation but the texture is tiled.");
597 }
598 std::size_t remaining_size =
599 dst_params.size_in_bytes_total - src_params.size_in_bytes_total;
600 std::vector<u8> data(remaining_size);
601 Memory::ReadBlock(dst_params.addr + src_params.size_in_bytes_total, data.data(),
602 data.size());
603 glBufferSubData(GL_PIXEL_PACK_BUFFER, src_params.size_in_bytes_total, remaining_size,
604 data.data());
605 }
606
607 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
608
609 const GLsizei width{static_cast<GLsizei>(
610 std::min(src_params.GetRect().GetWidth(), dst_params.GetRect().GetWidth()))};
611 const GLsizei height{static_cast<GLsizei>(
612 std::min(src_params.GetRect().GetHeight(), dst_params.GetRect().GetHeight()))};
613
614 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, copy_pbo_handle);
615 if (dest_format.compressed) {
616 LOG_CRITICAL(HW_GPU, "Compressed copy is unimplemented!");
617 UNREACHABLE();
618 } else {
619 switch (dst_params.target) {
620 case SurfaceParams::SurfaceTarget::Texture1D:
621 glTextureSubImage1D(dst_surface->Texture().handle, 0, 0, width, dest_format.format,
622 dest_format.type, nullptr);
623 break;
624 case SurfaceParams::SurfaceTarget::Texture2D:
625 glTextureSubImage2D(dst_surface->Texture().handle, 0, 0, 0, width, height,
626 dest_format.format, dest_format.type, nullptr);
627 break;
628 case SurfaceParams::SurfaceTarget::Texture3D:
629 case SurfaceParams::SurfaceTarget::Texture2DArray:
630 glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0, 0, width, height,
631 static_cast<GLsizei>(dst_params.depth), dest_format.format,
632 dest_format.type, nullptr);
633 break;
634 case SurfaceParams::SurfaceTarget::TextureCubemap:
635 glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0,
636 static_cast<GLint>(cubemap_face), width, height, 1,
637 dest_format.format, dest_format.type, nullptr);
638 break;
639 default:
640 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
641 static_cast<u32>(dst_params.target));
642 UNREACHABLE();
643 }
644 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
645 }
646}
647
541CachedSurface::CachedSurface(const SurfaceParams& params) 648CachedSurface::CachedSurface(const SurfaceParams& params)
542 : params(params), gl_target(SurfaceTargetToGL(params.target)) { 649 : params(params), gl_target(SurfaceTargetToGL(params.target)) {
543 texture.Create(); 650 texture.Create();
@@ -929,106 +1036,62 @@ Surface RasterizerCacheOpenGL::GetUncachedSurface(const SurfaceParams& params) {
929Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface, 1036Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
930 const SurfaceParams& new_params) { 1037 const SurfaceParams& new_params) {
931 // Verify surface is compatible for blitting 1038 // Verify surface is compatible for blitting
932 const auto& old_params{old_surface->GetSurfaceParams()}; 1039 auto old_params{old_surface->GetSurfaceParams()};
933 1040
934 // Get a new surface with the new parameters, and blit the previous surface to it 1041 // Get a new surface with the new parameters, and blit the previous surface to it
935 Surface new_surface{GetUncachedSurface(new_params)}; 1042 Surface new_surface{GetUncachedSurface(new_params)};
936 1043
937 if (old_params.pixel_format == new_params.pixel_format || 1044 // If the format is the same, just do a framebuffer blit. This is significantly faster than
938 !Settings::values.use_accurate_framebuffers) { 1045 // using PBOs. The is also likely less accurate, as textures will be converted rather than
939 // If the format is the same, just do a framebuffer blit. This is significantly faster than 1046 // reinterpreted. When use_accurate_framebuffers setting is enabled, perform a more accurate
940 // using PBOs. The is also likely less accurate, as textures will be converted rather than 1047 // surface copy, where pixels are reinterpreted as a new format (without conversion). This
941 // reinterpreted. 1048 // code path uses OpenGL PBOs and is quite slow.
1049 const bool is_blit{old_params.pixel_format == new_params.pixel_format ||
1050 !Settings::values.use_accurate_framebuffers};
942 1051
943 BlitSurface(old_surface, new_surface, read_framebuffer.handle, draw_framebuffer.handle); 1052 switch (new_params.target) {
944 } else { 1053 case SurfaceParams::SurfaceTarget::Texture2D:
945 // When use_accurate_framebuffers setting is enabled, perform a more accurate surface copy, 1054 if (is_blit) {
946 // where pixels are reinterpreted as a new format (without conversion). This code path uses 1055 BlitSurface(old_surface, new_surface, read_framebuffer.handle, draw_framebuffer.handle);
947 // OpenGL PBOs and is quite slow.
948
949 auto source_format = GetFormatTuple(old_params.pixel_format, old_params.component_type);
950 auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type);
951
952 std::size_t buffer_size =
953 std::max(old_params.size_in_bytes_total, new_params.size_in_bytes_total);
954
955 glBindBuffer(GL_PIXEL_PACK_BUFFER, copy_pbo.handle);
956 glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
957 if (source_format.compressed) {
958 glGetCompressedTextureImage(old_surface->Texture().handle, 0,
959 static_cast<GLsizei>(old_params.size_in_bytes_total),
960 nullptr);
961 } else { 1056 } else {
962 glGetTextureImage(old_surface->Texture().handle, 0, source_format.format, 1057 CopySurface(old_surface, new_surface, copy_pbo.handle);
963 source_format.type,
964 static_cast<GLsizei>(old_params.size_in_bytes_total), nullptr);
965 } 1058 }
966 // If the new texture is bigger than the previous one, we need to fill in the rest with data 1059 break;
967 // from the CPU. 1060 case SurfaceParams::SurfaceTarget::TextureCubemap: {
968 if (old_params.size_in_bytes_total < new_params.size_in_bytes_total) { 1061 const u32 byte_stride{old_params.rt.layer_stride *
969 // Upload the rest of the memory. 1062 (SurfaceParams::GetFormatBpp(old_params.pixel_format) / CHAR_BIT)};
970 if (new_params.is_tiled) { 1063
971 // TODO(Subv): We might have to de-tile the subtexture and re-tile it with the rest 1064 // This seems to be used for render-to-cubemap texture
972 // of the data in this case. Games like Super Mario Odyssey seem to hit this case 1065 const std::size_t size_with_mipmaps{new_params.SizeInBytes2DWithMipmap()};
973 // when drawing, it re-uses the memory of a previous texture as a bigger framebuffer 1066 ASSERT_MSG(size_with_mipmaps == byte_stride, "Unexpected");
974 // but it doesn't clear it beforehand, the texture is already full of zeros. 1067 ASSERT_MSG(old_params.target == SurfaceParams::SurfaceTarget::Texture2D, "Unexpected");
975 LOG_DEBUG(HW_GPU, "Trying to upload extra texture data from the CPU during " 1068 ASSERT_MSG(old_params.pixel_format == new_params.pixel_format, "Unexpected");
976 "reinterpretation but the texture is tiled."); 1069 ASSERT_MSG(old_params.width == new_params.width, "Unexpected");
1070 ASSERT_MSG(old_params.height == new_params.height, "Unexpected");
1071 ASSERT_MSG(old_params.rt.array_mode == 1, "Unexpected");
1072 ASSERT_MSG(old_params.rt.base_layer == 0, "Unimplemented");
1073
1074 for (std::size_t index = 0; index < new_params.depth; ++index) {
1075 Surface face_surface{TryGetReservedSurface(old_params)};
1076 ASSERT_MSG(face_surface, "Unexpected");
1077
1078 if (is_blit) {
1079 BlitSurface(face_surface, new_surface, read_framebuffer.handle,
1080 draw_framebuffer.handle, face_surface->GetSurfaceParams().rt.index,
1081 new_params.rt.index, index);
1082 } else {
1083 CopySurface(face_surface, new_surface, copy_pbo.handle,
1084 face_surface->GetSurfaceParams().rt.index, new_params.rt.index, index);
977 } 1085 }
978 std::size_t remaining_size =
979 new_params.size_in_bytes_total - old_params.size_in_bytes_total;
980 std::vector<u8> data(remaining_size);
981 Memory::ReadBlock(new_params.addr + old_params.size_in_bytes_total, data.data(),
982 data.size());
983 glBufferSubData(GL_PIXEL_PACK_BUFFER, old_params.size_in_bytes_total, remaining_size,
984 data.data());
985 }
986
987 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
988 1086
989 const auto& dest_rect{new_params.GetRect()}; 1087 old_params.addr += size_with_mipmaps;
990
991 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, copy_pbo.handle);
992 if (dest_format.compressed) {
993 LOG_CRITICAL(HW_GPU, "Compressed copy is unimplemented!");
994 UNREACHABLE();
995 } else {
996 switch (new_params.target) {
997 case SurfaceParams::SurfaceTarget::Texture1D:
998 glTextureSubImage1D(new_surface->Texture().handle, 0, 0,
999 static_cast<GLsizei>(dest_rect.GetWidth()), dest_format.format,
1000 dest_format.type, nullptr);
1001 break;
1002 case SurfaceParams::SurfaceTarget::Texture2D:
1003 glTextureSubImage2D(new_surface->Texture().handle, 0, 0, 0,
1004 static_cast<GLsizei>(dest_rect.GetWidth()),
1005 static_cast<GLsizei>(dest_rect.GetHeight()), dest_format.format,
1006 dest_format.type, nullptr);
1007 break;
1008 case SurfaceParams::SurfaceTarget::Texture3D:
1009 case SurfaceParams::SurfaceTarget::Texture2DArray:
1010 glTextureSubImage3D(new_surface->Texture().handle, 0, 0, 0, 0,
1011 static_cast<GLsizei>(dest_rect.GetWidth()),
1012 static_cast<GLsizei>(dest_rect.GetHeight()),
1013 static_cast<GLsizei>(new_params.depth), dest_format.format,
1014 dest_format.type, nullptr);
1015 break;
1016 case SurfaceParams::SurfaceTarget::TextureCubemap:
1017 for (std::size_t face = 0; face < new_params.depth; ++face) {
1018 glTextureSubImage3D(
1019 new_surface->Texture().handle, 0, 0, 0, static_cast<GLint>(face),
1020 static_cast<GLsizei>(dest_rect.GetWidth()),
1021 static_cast<GLsizei>(dest_rect.GetHeight()), static_cast<GLsizei>(1),
1022 dest_format.format, dest_format.type, nullptr);
1023 }
1024 break;
1025 default:
1026 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
1027 static_cast<u32>(new_params.target));
1028 UNREACHABLE();
1029 }
1030 } 1088 }
1031 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 1089 break;
1090 }
1091 default:
1092 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
1093 static_cast<u32>(new_params.target));
1094 UNREACHABLE();
1032 } 1095 }
1033 1096
1034 return new_surface; 1097 return new_surface;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index e2fd0009e..51eb9b6dd 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -9,6 +9,7 @@
9#include <memory> 9#include <memory>
10#include <vector> 10#include <vector>
11 11
12#include "common/alignment.h"
12#include "common/common_types.h" 13#include "common/common_types.h"
13#include "common/hash.h" 14#include "common/hash.h"
14#include "common/math_util.h" 15#include "common/math_util.h"
@@ -706,6 +707,29 @@ struct SurfaceParams {
706 return SizeInBytes2D() * depth; 707 return SizeInBytes2D() * depth;
707 } 708 }
708 709
710 /**
711 * Returns the size in bytes of the 2D surface with mipmaps. Each mipmap level proceeds the
712 * previous with half the width and half the height. Once the size of the next mip reaches 0, we
713 * are done.
714 */
715 std::size_t SizeInBytes2DWithMipmap() const {
716 std::size_t size_in_bytes{};
717 auto mip_params{*this};
718 for (std::size_t level = 0; level < max_mip_level; level++) {
719 size_in_bytes += mip_params.SizeInBytes2D();
720
721 mip_params.width /= 2;
722 mip_params.height /= 2;
723
724 if (!mip_params.width || !mip_params.height) {
725 break;
726 }
727 }
728
729 // TODO(bunnei): This alignup is unverified, but necessary in games tested (e.g. in SMO)
730 return Common::AlignUp(size_in_bytes, 0x1000);
731 }
732
709 /// Creates SurfaceParams from a texture configuration 733 /// Creates SurfaceParams from a texture configuration
710 static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config, 734 static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config,
711 const GLShader::SamplerEntry& entry); 735 const GLShader::SamplerEntry& entry);
@@ -738,6 +762,15 @@ struct SurfaceParams {
738 std::size_t size_in_bytes_total; 762 std::size_t size_in_bytes_total;
739 std::size_t size_in_bytes_2d; 763 std::size_t size_in_bytes_2d;
740 SurfaceTarget target; 764 SurfaceTarget target;
765 u32 max_mip_level;
766
767 // Render target specific parameters, not used in caching
768 struct {
769 u32 index;
770 u32 array_mode;
771 u32 layer_stride;
772 u32 base_layer;
773 } rt;
741}; 774};
742 775
743}; // namespace OpenGL 776}; // namespace OpenGL
@@ -747,6 +780,7 @@ struct SurfaceReserveKey : Common::HashableStruct<OpenGL::SurfaceParams> {
747 static SurfaceReserveKey Create(const OpenGL::SurfaceParams& params) { 780 static SurfaceReserveKey Create(const OpenGL::SurfaceParams& params) {
748 SurfaceReserveKey res; 781 SurfaceReserveKey res;
749 res.state = params; 782 res.state = params;
783 res.state.rt = {}; // Ignore rt config in caching
750 return res; 784 return res;
751 } 785 }
752}; 786};
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index c2fb824b2..14aea4838 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -165,6 +165,8 @@ struct TICEntry {
165 165
166 // High 16 bits of the pitch value 166 // High 16 bits of the pitch value
167 BitField<0, 16, u32> pitch_high; 167 BitField<0, 16, u32> pitch_high;
168
169 BitField<28, 4, u32> max_mip_level;
168 }; 170 };
169 union { 171 union {
170 BitField<0, 16, u32> width_minus_1; 172 BitField<0, 16, u32> width_minus_1;