diff options
Diffstat (limited to 'src/video_core/renderer_opengl')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 115 |
1 files changed, 13 insertions, 102 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index b5a9722f9..876698b37 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" | 21 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" |
| 22 | #include "video_core/renderer_opengl/utils.h" | 22 | #include "video_core/renderer_opengl/utils.h" |
| 23 | #include "video_core/surface.h" | 23 | #include "video_core/surface.h" |
| 24 | #include "video_core/textures/astc.h" | 24 | #include "video_core/textures/convert.h" |
| 25 | #include "video_core/textures/decoders.h" | 25 | #include "video_core/textures/decoders.h" |
| 26 | 26 | ||
| 27 | namespace OpenGL { | 27 | namespace OpenGL { |
| @@ -597,103 +597,6 @@ CachedSurface::CachedSurface(const SurfaceParams& params) | |||
| 597 | } | 597 | } |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height, bool reverse) { | ||
| 601 | union S8Z24 { | ||
| 602 | BitField<0, 24, u32> z24; | ||
| 603 | BitField<24, 8, u32> s8; | ||
| 604 | }; | ||
| 605 | static_assert(sizeof(S8Z24) == 4, "S8Z24 is incorrect size"); | ||
| 606 | |||
| 607 | union Z24S8 { | ||
| 608 | BitField<0, 8, u32> s8; | ||
| 609 | BitField<8, 24, u32> z24; | ||
| 610 | }; | ||
| 611 | static_assert(sizeof(Z24S8) == 4, "Z24S8 is incorrect size"); | ||
| 612 | |||
| 613 | S8Z24 s8z24_pixel{}; | ||
| 614 | Z24S8 z24s8_pixel{}; | ||
| 615 | constexpr auto bpp{GetBytesPerPixel(PixelFormat::S8Z24)}; | ||
| 616 | for (std::size_t y = 0; y < height; ++y) { | ||
| 617 | for (std::size_t x = 0; x < width; ++x) { | ||
| 618 | const std::size_t offset{bpp * (y * width + x)}; | ||
| 619 | if (reverse) { | ||
| 620 | std::memcpy(&z24s8_pixel, &data[offset], sizeof(Z24S8)); | ||
| 621 | s8z24_pixel.s8.Assign(z24s8_pixel.s8); | ||
| 622 | s8z24_pixel.z24.Assign(z24s8_pixel.z24); | ||
| 623 | std::memcpy(&data[offset], &s8z24_pixel, sizeof(S8Z24)); | ||
| 624 | } else { | ||
| 625 | std::memcpy(&s8z24_pixel, &data[offset], sizeof(S8Z24)); | ||
| 626 | z24s8_pixel.s8.Assign(s8z24_pixel.s8); | ||
| 627 | z24s8_pixel.z24.Assign(s8z24_pixel.z24); | ||
| 628 | std::memcpy(&data[offset], &z24s8_pixel, sizeof(Z24S8)); | ||
| 629 | } | ||
| 630 | } | ||
| 631 | } | ||
| 632 | } | ||
| 633 | |||
| 634 | /** | ||
| 635 | * Helper function to perform software conversion (as needed) when loading a buffer from Switch | ||
| 636 | * memory. This is for Maxwell pixel formats that cannot be represented as-is in OpenGL or with | ||
| 637 | * typical desktop GPUs. | ||
| 638 | */ | ||
| 639 | static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, | ||
| 640 | u32 width, u32 height, u32 depth) { | ||
| 641 | switch (pixel_format) { | ||
| 642 | case PixelFormat::ASTC_2D_4X4: | ||
| 643 | case PixelFormat::ASTC_2D_8X8: | ||
| 644 | case PixelFormat::ASTC_2D_8X5: | ||
| 645 | case PixelFormat::ASTC_2D_5X4: | ||
| 646 | case PixelFormat::ASTC_2D_5X5: | ||
| 647 | case PixelFormat::ASTC_2D_4X4_SRGB: | ||
| 648 | case PixelFormat::ASTC_2D_8X8_SRGB: | ||
| 649 | case PixelFormat::ASTC_2D_8X5_SRGB: | ||
| 650 | case PixelFormat::ASTC_2D_5X4_SRGB: | ||
| 651 | case PixelFormat::ASTC_2D_5X5_SRGB: | ||
| 652 | case PixelFormat::ASTC_2D_10X8: | ||
| 653 | case PixelFormat::ASTC_2D_10X8_SRGB: { | ||
| 654 | // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC. | ||
| 655 | u32 block_width{}; | ||
| 656 | u32 block_height{}; | ||
| 657 | std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format); | ||
| 658 | data = | ||
| 659 | Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height); | ||
| 660 | break; | ||
| 661 | } | ||
| 662 | case PixelFormat::S8Z24: | ||
| 663 | // Convert the S8Z24 depth format to Z24S8, as OpenGL does not support S8Z24. | ||
| 664 | ConvertS8Z24ToZ24S8(data, width, height, false); | ||
| 665 | break; | ||
| 666 | } | ||
| 667 | } | ||
| 668 | |||
| 669 | /** | ||
| 670 | * Helper function to perform software conversion (as needed) when flushing a buffer from OpenGL to | ||
| 671 | * Switch memory. This is for Maxwell pixel formats that cannot be represented as-is in OpenGL or | ||
| 672 | * with typical desktop GPUs. | ||
| 673 | */ | ||
| 674 | static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, | ||
| 675 | u32 width, u32 height) { | ||
| 676 | switch (pixel_format) { | ||
| 677 | case PixelFormat::ASTC_2D_4X4: | ||
| 678 | case PixelFormat::ASTC_2D_8X8: | ||
| 679 | case PixelFormat::ASTC_2D_4X4_SRGB: | ||
| 680 | case PixelFormat::ASTC_2D_8X8_SRGB: | ||
| 681 | case PixelFormat::ASTC_2D_5X5: | ||
| 682 | case PixelFormat::ASTC_2D_5X5_SRGB: | ||
| 683 | case PixelFormat::ASTC_2D_10X8: | ||
| 684 | case PixelFormat::ASTC_2D_10X8_SRGB: { | ||
| 685 | LOG_CRITICAL(HW_GPU, "Conversion of format {} after texture flushing is not implemented", | ||
| 686 | static_cast<u32>(pixel_format)); | ||
| 687 | UNREACHABLE(); | ||
| 688 | break; | ||
| 689 | } | ||
| 690 | case PixelFormat::S8Z24: | ||
| 691 | // Convert the Z24S8 depth format to S8Z24, as OpenGL does not support S8Z24. | ||
| 692 | ConvertS8Z24ToZ24S8(data, width, height, true); | ||
| 693 | break; | ||
| 694 | } | ||
| 695 | } | ||
| 696 | |||
| 697 | MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 192, 64)); | 600 | MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 192, 64)); |
| 698 | void CachedSurface::LoadGLBuffer() { | 601 | void CachedSurface::LoadGLBuffer() { |
| 699 | MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); | 602 | MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); |
| @@ -722,8 +625,16 @@ void CachedSurface::LoadGLBuffer() { | |||
| 722 | } | 625 | } |
| 723 | } | 626 | } |
| 724 | for (u32 i = 0; i < params.max_mip_level; i++) { | 627 | for (u32 i = 0; i < params.max_mip_level; i++) { |
| 725 | ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), | 628 | const u32 width = params.MipWidth(i); |
| 726 | params.MipHeight(i), params.MipDepth(i)); | 629 | const u32 height = params.MipHeight(i); |
| 630 | const u32 depth = params.MipDepth(i); | ||
| 631 | if (VideoCore::Surface::IsPixelFormatASTC(params.pixel_format)) { | ||
| 632 | // Reserve size for RGBA8 conversion | ||
| 633 | constexpr std::size_t rgba_bpp = 4; | ||
| 634 | gl_buffer[i].resize(std::max(gl_buffer[i].size(), width * height * depth * rgba_bpp)); | ||
| 635 | } | ||
| 636 | Tegra::Texture::ConvertFromGuestToHost(gl_buffer[i].data(), params.pixel_format, width, | ||
| 637 | height, depth, true, true); | ||
| 727 | } | 638 | } |
| 728 | } | 639 | } |
| 729 | 640 | ||
| @@ -746,8 +657,8 @@ void CachedSurface::FlushGLBuffer() { | |||
| 746 | glGetTextureImage(texture.handle, 0, tuple.format, tuple.type, | 657 | glGetTextureImage(texture.handle, 0, tuple.format, tuple.type, |
| 747 | static_cast<GLsizei>(gl_buffer[0].size()), gl_buffer[0].data()); | 658 | static_cast<GLsizei>(gl_buffer[0].size()), gl_buffer[0].data()); |
| 748 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); | 659 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); |
| 749 | ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer[0], params.pixel_format, params.width, | 660 | Tegra::Texture::ConvertFromHostToGuest(gl_buffer[0].data(), params.pixel_format, params.width, |
| 750 | params.height); | 661 | params.height, params.depth, true, true); |
| 751 | const u8* const texture_src_data = Memory::GetPointer(params.addr); | 662 | const u8* const texture_src_data = Memory::GetPointer(params.addr); |
| 752 | ASSERT(texture_src_data); | 663 | ASSERT(texture_src_data); |
| 753 | if (params.is_tiled) { | 664 | if (params.is_tiled) { |