diff options
| author | bunnei <bunneidev@gmail.com> | 2018-11-04 18:47:26 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-04 18:47:26 -0500 | 
| commit | 38c1c500ab733208d86972f61c29d6679c502c31 (patch) | |
| tree | cfe859b9c8f92bada0c6902953470e627769d9ec | |
| parent | d46e0acb3c52ebfd8fdcd036e6e1483932f9c469 (diff) | |
| parent | 60a184455c5aef7cce7e6232cab738f66cb0aac0 (diff) | |
Merge pull request #1625 from FernandoS27/astc
Implement ASTC Textures 5x5 and fix a bunch of ASTC texture problems
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 38 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 2 | ||||
| -rw-r--r-- | src/video_core/surface.cpp | 26 | ||||
| -rw-r--r-- | src/video_core/surface.h | 107 | ||||
| -rw-r--r-- | src/video_core/textures/astc.cpp | 32 | ||||
| -rw-r--r-- | src/video_core/textures/astc.h | 2 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.h | 4 | ||||
| -rw-r--r-- | src/yuzu/debugger/graphics/graphics_surface.cpp | 6 | 
9 files changed, 154 insertions, 75 deletions
| diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index f194a7687..0e11557c4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -58,16 +58,14 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {  std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only,                                                   bool uncompressed) const { -    const u32 compression_factor{GetCompressionFactor(pixel_format)}; +    const u32 tile_x{GetDefaultBlockWidth(pixel_format)}; +    const u32 tile_y{GetDefaultBlockHeight(pixel_format)};      const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)};      u32 m_depth = (layer_only ? 1U : depth);      u32 m_width = MipWidth(mip_level);      u32 m_height = MipHeight(mip_level); -    m_width = uncompressed ? m_width -                           : std::max(1U, (m_width + compression_factor - 1) / compression_factor); -    m_height = uncompressed -                   ? m_height -                   : std::max(1U, (m_height + compression_factor - 1) / compression_factor); +    m_width = uncompressed ? m_width : std::max(1U, (m_width + tile_x - 1) / tile_x); +    m_height = uncompressed ? m_height : std::max(1U, (m_height + tile_y - 1) / tile_y);      m_depth = std::max(1U, m_depth >> mip_level);      u32 m_block_height = MipBlockHeight(mip_level);      u32 m_block_depth = MipBlockDepth(mip_level); @@ -305,6 +303,8 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex      {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB      {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB      {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB +    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false},        // ASTC_2D_5X5 +    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB      // Depth formats      {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F @@ -364,15 +364,18 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 d      // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual      // pixel values. -    const u32 tile_size{IsFormatBCn(format) ? 4U : 1U}; +    const u32 tile_size_x{GetDefaultBlockWidth(format)}; +    const u32 tile_size_y{GetDefaultBlockHeight(format)};      if (morton_to_gl) { -        const std::vector<u8> data = Tegra::Texture::UnswizzleTexture( -            addr, tile_size, bytes_per_pixel, stride, height, depth, block_height, block_depth); +        const std::vector<u8> data = +            Tegra::Texture::UnswizzleTexture(addr, tile_size_x, tile_size_y, bytes_per_pixel, +                                             stride, height, depth, block_height, block_depth);          const std::size_t size_to_copy{std::min(gl_buffer_size, data.size())};          memcpy(gl_buffer, data.data(), size_to_copy);      } else { -        Tegra::Texture::CopySwizzledData(stride / tile_size, height / tile_size, depth, +        Tegra::Texture::CopySwizzledData((stride + tile_size_x - 1) / tile_size_x, +                                         (height + tile_size_y - 1) / tile_size_y, depth,                                           bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr),                                           gl_buffer, false, block_height, block_depth);      } @@ -440,6 +443,8 @@ static constexpr GLConversionArray morton_to_gl_fns = {          MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,          MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,          MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>, +        MortonCopy<true, PixelFormat::ASTC_2D_5X5>, +        MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,          MortonCopy<true, PixelFormat::Z32F>,          MortonCopy<true, PixelFormat::Z16>,          MortonCopy<true, PixelFormat::Z24S8>, @@ -508,6 +513,8 @@ static constexpr GLConversionArray gl_to_morton_fns = {          nullptr,          nullptr,          nullptr, +        nullptr, +        nullptr,          MortonCopy<false, PixelFormat::Z32F>,          MortonCopy<false, PixelFormat::Z16>,          MortonCopy<false, PixelFormat::Z24S8>, @@ -897,21 +904,24 @@ static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {   * typical desktop GPUs.   */  static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, -                                               u32 width, u32 height) { +                                               u32 width, u32 height, u32 depth) {      switch (pixel_format) {      case PixelFormat::ASTC_2D_4X4:      case PixelFormat::ASTC_2D_8X8:      case PixelFormat::ASTC_2D_8X5:      case PixelFormat::ASTC_2D_5X4: +    case PixelFormat::ASTC_2D_5X5:      case PixelFormat::ASTC_2D_4X4_SRGB:      case PixelFormat::ASTC_2D_8X8_SRGB:      case PixelFormat::ASTC_2D_8X5_SRGB: -    case PixelFormat::ASTC_2D_5X4_SRGB: { +    case PixelFormat::ASTC_2D_5X4_SRGB: +    case PixelFormat::ASTC_2D_5X5_SRGB: {          // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.          u32 block_width{};          u32 block_height{};          std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format); -        data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height); +        data = +            Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height);          break;      }      case PixelFormat::S8Z24: @@ -971,7 +981,7 @@ void CachedSurface::LoadGLBuffer() {      }      for (u32 i = 0; i < params.max_mip_level; i++)          ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), -                                           params.MipHeight(i)); +                                           params.MipHeight(i), params.MipDepth(i));  }  MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index f255f4419..46ad37897 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -139,7 +139,7 @@ struct SurfaceParams {      }      u32 MipDepth(u32 mip_level) const { -        return std::max(1U, depth >> mip_level); +        return is_layered ? depth : std::max(1U, depth >> mip_level);      }      // Auto block resizing algorithm from: diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index d9a97e30b..e284a4604 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -297,6 +297,8 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,          return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4;      case Tegra::Texture::TextureFormat::ASTC_2D_5X4:          return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4; +    case Tegra::Texture::TextureFormat::ASTC_2D_5X5: +        return is_srgb ? PixelFormat::ASTC_2D_5X5_SRGB : PixelFormat::ASTC_2D_5X5;      case Tegra::Texture::TextureFormat::ASTC_2D_8X8:          return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;      case Tegra::Texture::TextureFormat::ASTC_2D_8X5: @@ -440,10 +442,12 @@ bool IsPixelFormatASTC(PixelFormat format) {      switch (format) {      case PixelFormat::ASTC_2D_4X4:      case PixelFormat::ASTC_2D_5X4: +    case PixelFormat::ASTC_2D_5X5:      case PixelFormat::ASTC_2D_8X8:      case PixelFormat::ASTC_2D_8X5:      case PixelFormat::ASTC_2D_4X4_SRGB:      case PixelFormat::ASTC_2D_5X4_SRGB: +    case PixelFormat::ASTC_2D_5X5_SRGB:      case PixelFormat::ASTC_2D_8X8_SRGB:      case PixelFormat::ASTC_2D_8X5_SRGB:          return true; @@ -453,27 +457,7 @@ bool IsPixelFormatASTC(PixelFormat format) {  }  std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) { -    switch (format) { -    case PixelFormat::ASTC_2D_4X4: -        return {4, 4}; -    case PixelFormat::ASTC_2D_5X4: -        return {5, 4}; -    case PixelFormat::ASTC_2D_8X8: -        return {8, 8}; -    case PixelFormat::ASTC_2D_8X5: -        return {8, 5}; -    case PixelFormat::ASTC_2D_4X4_SRGB: -        return {4, 4}; -    case PixelFormat::ASTC_2D_5X4_SRGB: -        return {5, 4}; -    case PixelFormat::ASTC_2D_8X8_SRGB: -        return {8, 8}; -    case PixelFormat::ASTC_2D_8X5_SRGB: -        return {8, 5}; -    default: -        LOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format)); -        UNREACHABLE(); -    } +    return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)};  }  bool IsFormatBCn(PixelFormat format) { diff --git a/src/video_core/surface.h b/src/video_core/surface.h index 3232e437f..0ef7849a4 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h @@ -72,19 +72,21 @@ enum class PixelFormat {      ASTC_2D_8X8_SRGB = 54,      ASTC_2D_8X5_SRGB = 55,      ASTC_2D_5X4_SRGB = 56, +    ASTC_2D_5X5 = 57, +    ASTC_2D_5X5_SRGB = 58,      MaxColorFormat,      // Depth formats -    Z32F = 57, -    Z16 = 58, +    Z32F = 59, +    Z16 = 60,      MaxDepthFormat,      // DepthStencil formats -    Z24S8 = 59, -    S8Z24 = 60, -    Z32FS8 = 61, +    Z24S8 = 61, +    S8Z24 = 62, +    Z32FS8 = 63,      MaxDepthStencilFormat, @@ -188,6 +190,8 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) {          4, // ASTC_2D_8X8_SRGB          4, // ASTC_2D_8X5_SRGB          4, // ASTC_2D_5X4_SRGB +        4, // ASTC_2D_5X5 +        4, // ASTC_2D_5X5_SRGB          1, // Z32F          1, // Z16          1, // Z24S8 @@ -199,6 +203,79 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) {      return compression_factor_table[static_cast<std::size_t>(format)];  } +static constexpr u32 GetDefaultBlockWidth(PixelFormat format) { +    if (format == PixelFormat::Invalid) +        return 0; +    constexpr std::array<u32, MaxPixelFormat> block_width_table = {{ +        1, // ABGR8U +        1, // ABGR8S +        1, // ABGR8UI +        1, // B5G6R5U +        1, // A2B10G10R10U +        1, // A1B5G5R5U +        1, // R8U +        1, // R8UI +        1, // RGBA16F +        1, // RGBA16U +        1, // RGBA16UI +        1, // R11FG11FB10F +        1, // RGBA32UI +        4, // DXT1 +        4, // DXT23 +        4, // DXT45 +        4, // DXN1 +        4, // DXN2UNORM +        4, // DXN2SNORM +        4, // BC7U +        4, // BC6H_UF16 +        4, // BC6H_SF16 +        4, // ASTC_2D_4X4 +        1, // G8R8U +        1, // G8R8S +        1, // BGRA8 +        1, // RGBA32F +        1, // RG32F +        1, // R32F +        1, // R16F +        1, // R16U +        1, // R16S +        1, // R16UI +        1, // R16I +        1, // RG16 +        1, // RG16F +        1, // RG16UI +        1, // RG16I +        1, // RG16S +        1, // RGB32F +        1, // RGBA8_SRGB +        1, // RG8U +        1, // RG8S +        1, // RG32UI +        1, // R32UI +        8, // ASTC_2D_8X8 +        8, // ASTC_2D_8X5 +        5, // ASTC_2D_5X4 +        1, // BGRA8_SRGB +        4, // DXT1_SRGB +        4, // DXT23_SRGB +        4, // DXT45_SRGB +        4, // BC7U_SRGB +        4, // ASTC_2D_4X4_SRGB +        8, // ASTC_2D_8X8_SRGB +        8, // ASTC_2D_8X5_SRGB +        5, // ASTC_2D_5X4_SRGB +        5, // ASTC_2D_5X5 +        5, // ASTC_2D_5X5_SRGB +        1, // Z32F +        1, // Z16 +        1, // Z24S8 +        1, // S8Z24 +        1, // Z32FS8 +    }}; +    ASSERT(static_cast<std::size_t>(format) < block_width_table.size()); +    return block_width_table[static_cast<std::size_t>(format)]; +} +  static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {      if (format == PixelFormat::Invalid)          return 0; @@ -261,6 +338,8 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {          8, // ASTC_2D_8X8_SRGB          5, // ASTC_2D_8X5_SRGB          4, // ASTC_2D_5X4_SRGB +        5, // ASTC_2D_5X5 +        5, // ASTC_2D_5X5_SRGB          1, // Z32F          1, // Z16          1, // Z24S8 @@ -299,7 +378,7 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {          128, // BC7U          128, // BC6H_UF16          128, // BC6H_SF16 -        32,  // ASTC_2D_4X4 +        128, // ASTC_2D_4X4          16,  // G8R8U          16,  // G8R8S          32,  // BGRA8 @@ -322,18 +401,20 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {          16,  // RG8S          64,  // RG32UI          32,  // R32UI -        16,  // ASTC_2D_8X8 -        16,  // ASTC_2D_8X5 -        32,  // ASTC_2D_5X4 +        128, // ASTC_2D_8X8 +        128, // ASTC_2D_8X5 +        128, // ASTC_2D_5X4          32,  // BGRA8_SRGB          64,  // DXT1_SRGB          128, // DXT23_SRGB          128, // DXT45_SRGB          128, // BC7U -        32,  // ASTC_2D_4X4_SRGB -        16,  // ASTC_2D_8X8_SRGB -        16,  // ASTC_2D_8X5_SRGB -        32,  // ASTC_2D_5X4_SRGB +        128, // ASTC_2D_4X4_SRGB +        128, // ASTC_2D_8X8_SRGB +        128, // ASTC_2D_8X5_SRGB +        128, // ASTC_2D_5X4_SRGB +        128, // ASTC_2D_5X5 +        128, // ASTC_2D_5X5_SRGB          32,  // Z32F          16,  // Z16          32,  // Z24S8 diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp index b1feacae9..bc50a4876 100644 --- a/src/video_core/textures/astc.cpp +++ b/src/video_core/textures/astc.cpp @@ -1598,27 +1598,29 @@ static void DecompressBlock(uint8_t inBuf[16], const uint32_t blockWidth,  namespace Tegra::Texture::ASTC {  std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, -                                uint32_t block_width, uint32_t block_height) { +                                uint32_t depth, uint32_t block_width, uint32_t block_height) {      uint32_t blockIdx = 0; -    std::vector<uint8_t> outData(height * width * 4); -    for (uint32_t j = 0; j < height; j += block_height) { -        for (uint32_t i = 0; i < width; i += block_width) { +    std::vector<uint8_t> outData(height * width * depth * 4); +    for (uint32_t k = 0; k < depth; k++) { +        for (uint32_t j = 0; j < height; j += block_height) { +            for (uint32_t i = 0; i < width; i += block_width) { -            uint8_t* blockPtr = data.data() + blockIdx * 16; +                uint8_t* blockPtr = data.data() + blockIdx * 16; -            // Blocks can be at most 12x12 -            uint32_t uncompData[144]; -            ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData); +                // Blocks can be at most 12x12 +                uint32_t uncompData[144]; +                ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData); -            uint32_t decompWidth = std::min(block_width, width - i); -            uint32_t decompHeight = std::min(block_height, height - j); +                uint32_t decompWidth = std::min(block_width, width - i); +                uint32_t decompHeight = std::min(block_height, height - j); -            uint8_t* outRow = outData.data() + (j * width + i) * 4; -            for (uint32_t jj = 0; jj < decompHeight; jj++) { -                memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4); -            } +                uint8_t* outRow = outData.data() + (j * width + i) * 4; +                for (uint32_t jj = 0; jj < decompHeight; jj++) { +                    memcpy(outRow + jj * width * 4, uncompData + jj * block_width, decompWidth * 4); +                } -            blockIdx++; +                blockIdx++; +            }          }      } diff --git a/src/video_core/textures/astc.h b/src/video_core/textures/astc.h index f0d7c0e56..d419dd025 100644 --- a/src/video_core/textures/astc.h +++ b/src/video_core/textures/astc.h @@ -10,6 +10,6 @@  namespace Tegra::Texture::ASTC {  std::vector<uint8_t> Decompress(std::vector<uint8_t>& data, uint32_t width, uint32_t height, -                                uint32_t block_width, uint32_t block_height); +                                uint32_t depth, uint32_t block_width, uint32_t block_height);  } // namespace Tegra::Texture::ASTC diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 550ca856c..3066abf61 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -227,12 +227,14 @@ u32 BytesPerPixel(TextureFormat format) {      }  } -std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width, -                                 u32 height, u32 depth, u32 block_height, u32 block_depth) { +std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y, +                                 u32 bytes_per_pixel, u32 width, u32 height, u32 depth, +                                 u32 block_height, u32 block_depth) {      std::vector<u8> unswizzled_data(width * height * depth * bytes_per_pixel); -    CopySwizzledData(width / tile_size, height / tile_size, depth, bytes_per_pixel, bytes_per_pixel, -                     Memory::GetPointer(address), unswizzled_data.data(), true, block_height, -                     block_depth); +    CopySwizzledData((width + tile_size_x - 1) / tile_size_x, +                     (height + tile_size_y - 1) / tile_size_y, depth, bytes_per_pixel, +                     bytes_per_pixel, Memory::GetPointer(address), unswizzled_data.data(), true, +                     block_height, block_depth);      return unswizzled_data;  } diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index b390219e4..ba065510b 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h @@ -19,8 +19,8 @@ inline std::size_t GetGOBSize() {  /**   * Unswizzles a swizzled texture without changing its format.   */ -std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width, -                                 u32 height, u32 depth, +std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size_x, u32 tile_size_y, +                                 u32 bytes_per_pixel, u32 width, u32 height, u32 depth,                                   u32 block_height = TICEntry::DefaultBlockHeight,                                   u32 block_depth = TICEntry::DefaultBlockHeight); diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp index 0adbab27d..707747422 100644 --- a/src/yuzu/debugger/graphics/graphics_surface.cpp +++ b/src/yuzu/debugger/graphics/graphics_surface.cpp @@ -386,9 +386,9 @@ void GraphicsSurfaceWidget::OnUpdate() {      // TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles.      // Needs to be fixed if we plan to use this feature more, otherwise we may remove it. -    auto unswizzled_data = -        Tegra::Texture::UnswizzleTexture(*address, 1, Tegra::Texture::BytesPerPixel(surface_format), -                                         surface_width, surface_height, 1U); +    auto unswizzled_data = Tegra::Texture::UnswizzleTexture( +        *address, 1, 1, Tegra::Texture::BytesPerPixel(surface_format), surface_width, +        surface_height, 1U);      auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,                                                        surface_width, surface_height); | 
