rasterizer_cache: Separate texture swizzling to utils
This commit is contained in:
		| @@ -33,12 +33,17 @@ void CachedSurface::LoadGLBuffer(PAddr load_start, PAddr load_end) { | ||||
|     const bool need_swap = | ||||
|         GLES && (pixel_format == PixelFormat::RGBA8 || pixel_format == PixelFormat::RGB8); | ||||
|  | ||||
|     const u8* const texture_src_data = VideoCore::g_memory->GetPhysicalPointer(addr); | ||||
|     if (texture_src_data == nullptr) | ||||
|     const u8* texture_ptr = VideoCore::g_memory->GetPhysicalPointer(addr); | ||||
|     if (texture_ptr == nullptr) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     const u32 byte_size = width * height * GetBytesPerPixel(pixel_format); | ||||
|     const auto texture_data = std::span<const std::byte>{reinterpret_cast<const std::byte*>(texture_ptr), | ||||
|                                                          byte_size}; | ||||
|  | ||||
|     if (gl_buffer.empty()) { | ||||
|         gl_buffer.resize(width * height * GetBytesPerPixel(pixel_format)); | ||||
|         gl_buffer.resize(byte_size); | ||||
|     } | ||||
|  | ||||
|     // TODO: Should probably be done in ::Memory:: and check for other regions too | ||||
| @@ -60,48 +65,26 @@ void CachedSurface::LoadGLBuffer(PAddr load_start, PAddr load_end) { | ||||
|             // cannot fully test this | ||||
|             if (pixel_format == PixelFormat::RGBA8) { | ||||
|                 for (std::size_t i = start_offset; i < load_end - addr; i += 4) { | ||||
|                     gl_buffer[i] = texture_src_data[i + 3]; | ||||
|                     gl_buffer[i + 1] = texture_src_data[i + 2]; | ||||
|                     gl_buffer[i + 2] = texture_src_data[i + 1]; | ||||
|                     gl_buffer[i + 3] = texture_src_data[i]; | ||||
|                     gl_buffer[i] = texture_ptr[i + 3]; | ||||
|                     gl_buffer[i + 1] = texture_ptr[i + 2]; | ||||
|                     gl_buffer[i + 2] = texture_ptr[i + 1]; | ||||
|                     gl_buffer[i + 3] = texture_ptr[i]; | ||||
|                 } | ||||
|             } else if (pixel_format == PixelFormat::RGB8) { | ||||
|                 for (std::size_t i = start_offset; i < load_end - addr; i += 3) { | ||||
|                     gl_buffer[i] = texture_src_data[i + 2]; | ||||
|                     gl_buffer[i + 1] = texture_src_data[i + 1]; | ||||
|                     gl_buffer[i + 2] = texture_src_data[i]; | ||||
|                     gl_buffer[i] = texture_ptr[i + 2]; | ||||
|                     gl_buffer[i + 1] = texture_ptr[i + 1]; | ||||
|                     gl_buffer[i + 2] = texture_ptr[i]; | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset, | ||||
|             std::memcpy(&gl_buffer[start_offset], texture_ptr + start_offset, | ||||
|                         load_end - load_start); | ||||
|         } | ||||
|     } else { | ||||
|         if (type == SurfaceType::Texture) { | ||||
|             Pica::Texture::TextureInfo tex_info{}; | ||||
|             tex_info.width = width; | ||||
|             tex_info.height = height; | ||||
|             tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(pixel_format); | ||||
|             tex_info.SetDefaultStride(); | ||||
|             tex_info.physical_address = addr; | ||||
|  | ||||
|             const SurfaceInterval load_interval(load_start, load_end); | ||||
|             const auto rect = GetSubRect(FromInterval(load_interval)); | ||||
|             ASSERT(FromInterval(load_interval).GetInterval() == load_interval); | ||||
|  | ||||
|             for (unsigned y = rect.bottom; y < rect.top; ++y) { | ||||
|                 for (unsigned x = rect.left; x < rect.right; ++x) { | ||||
|                     auto vec4 = | ||||
|                         Pica::Texture::LookupTexture(texture_src_data, x, height - 1 - y, tex_info); | ||||
|                     const std::size_t offset = (x + (width * y)) * 4; | ||||
|                     std::memcpy(&gl_buffer[offset], vec4.AsArray(), 4); | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             const u32 func_index = static_cast<u32>(pixel_format); | ||||
|             const MortonFunc func = UNSWIZZLE_TABLE[func_index]; | ||||
|             func(stride, height, &gl_buffer[0], addr, load_start, load_end); | ||||
|         } | ||||
|         const auto dest_data = std::span<std::byte>{reinterpret_cast<std::byte*>(gl_buffer.data()), | ||||
|                                                     byte_size}; | ||||
|         UnswizzleTexture(*this, load_start, load_end, texture_data, dest_data); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -109,10 +92,12 @@ MICROPROFILE_DEFINE(RasterizerCache_SurfaceFlush, "RasterizerCache", "Surface Fl | ||||
|                     MP_RGB(128, 192, 64)); | ||||
| void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) { | ||||
|     u8* const dst_buffer = VideoCore::g_memory->GetPhysicalPointer(addr); | ||||
|     if (dst_buffer == nullptr) | ||||
|     if (dst_buffer == nullptr) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     ASSERT(gl_buffer.size() == width * height * GetBytesPerPixel(pixel_format)); | ||||
|     const u32 byte_size = width * height * GetBytesPerPixel(pixel_format); | ||||
|     DEBUG_ASSERT(gl_buffer.size() == byte_size); | ||||
|  | ||||
|     // TODO: Should probably be done in ::Memory:: and check for other regions too | ||||
|     // same as loadglbuffer() | ||||
| @@ -132,8 +117,9 @@ void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) { | ||||
|         const u32 coarse_start_offset = start_offset - (start_offset % fill_size); | ||||
|         const u32 backup_bytes = start_offset % fill_size; | ||||
|         std::array<u8, 4> backup_data; | ||||
|         if (backup_bytes) | ||||
|         if (backup_bytes) { | ||||
|             std::memcpy(&backup_data[0], &dst_buffer[coarse_start_offset], backup_bytes); | ||||
|         } | ||||
|  | ||||
|         for (u32 offset = coarse_start_offset; offset < end_offset; offset += fill_size) { | ||||
|             std::memcpy(&dst_buffer[offset], &fill_data[0], | ||||
| @@ -162,9 +148,9 @@ void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) { | ||||
|                         flush_end - flush_start); | ||||
|         } | ||||
|     } else { | ||||
|         const u32 func_index = static_cast<u32>(pixel_format); | ||||
|         const MortonFunc func = SWIZZLE_TABLE[func_index]; | ||||
|         func(stride, height, &gl_buffer[0], addr, flush_start, flush_end); | ||||
|         const auto source_data = std::span<std::byte>{reinterpret_cast<std::byte*>(gl_buffer.data()), | ||||
|                                                       byte_size}; | ||||
|         SwizzleTexture(*this, flush_start, flush_end, source_data, {}); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -451,7 +451,8 @@ Surface RasterizerCache::GetTextureSurface(const Pica::Texture::TextureInfo& inf | ||||
|  | ||||
|                     const Subresource dst_subresource = { | ||||
|                         .aspect = aspect, | ||||
|                         .region = surface_params.GetScaledRect() | ||||
|                         .region = surface_params.GetScaledRect(), | ||||
|                         .level = level | ||||
|                     }; | ||||
|  | ||||
|                     runtime.BlitTextures(level_surface->texture, src_subresource, | ||||
|   | ||||
| @@ -5,6 +5,8 @@ | ||||
| #pragma once | ||||
| #include <glad/glad.h> | ||||
| #include "video_core/texture/texture_decode.h" | ||||
| #include "video_core/rasterizer_cache/morton_swizzle.h" | ||||
| #include "video_core/rasterizer_cache/surface_params.h" | ||||
| #include "video_core/rasterizer_cache/utils.h" | ||||
| #include "video_core/renderer_opengl/gl_vars.h" | ||||
|  | ||||
| @@ -54,6 +56,49 @@ const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { | ||||
|     return tex_tuple; | ||||
| } | ||||
|  | ||||
| void SwizzleTexture(const SurfaceParams& params, u32 flush_start, u32 flush_end, | ||||
|                     std::span<std::byte> source, std::span<std::byte> dest) { | ||||
|     const u32 func_index = static_cast<u32>(params.pixel_format); | ||||
|     const MortonFunc swizzle = SWIZZLE_TABLE[func_index]; | ||||
|     u8* source_data = reinterpret_cast<u8*>(source.data()); | ||||
|  | ||||
|     // TODO: Move memory access out of the morton function | ||||
|     swizzle(params.stride, params.height, source_data, params.addr, flush_start, flush_end); | ||||
| } | ||||
|  | ||||
| void UnswizzleTexture(const SurfaceParams& params, u32 load_start, u32 load_end, | ||||
|                       std::span<const std::byte> source, std::span<std::byte> dest) { | ||||
|     // TODO: Integrate this to UNSWIZZLE_TABLE | ||||
|     if (params.type == SurfaceType::Texture) { | ||||
|         Pica::Texture::TextureInfo tex_info{}; | ||||
|         tex_info.width = params.width; | ||||
|         tex_info.height = params.height; | ||||
|         tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(params.pixel_format); | ||||
|         tex_info.SetDefaultStride(); | ||||
|         tex_info.physical_address = params.addr; | ||||
|  | ||||
|         const SurfaceInterval load_interval(load_start, load_end); | ||||
|         const auto rect = params.GetSubRect(params.FromInterval(load_interval)); | ||||
|         DEBUG_ASSERT(params.FromInterval(load_interval).GetInterval() == load_interval); | ||||
|  | ||||
|         const u8* source_data = reinterpret_cast<const u8*>(source.data()); | ||||
|         for (u32 y = rect.bottom; y < rect.top; y++) { | ||||
|             for (u32 x = rect.left; x < rect.right; x++) { | ||||
|                 auto vec4 = | ||||
|                     Pica::Texture::LookupTexture(source_data, x, params.height - 1 - y, tex_info); | ||||
|                 const std::size_t offset = (x + (params.width * y)) * 4; | ||||
|                 std::memcpy(dest.data() + offset, vec4.AsArray(), 4); | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         const u32 func_index = static_cast<u32>(params.pixel_format); | ||||
|         const MortonFunc deswizzle = UNSWIZZLE_TABLE[func_index]; | ||||
|         u8* dest_data = reinterpret_cast<u8*>(dest.data()); | ||||
|  | ||||
|         deswizzle(params.stride, params.height, dest_data, params.addr, load_start, load_end); | ||||
|     } | ||||
| } | ||||
|  | ||||
| ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data) { | ||||
|     ClearValue result{}; | ||||
|     switch (aspect) { | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  | ||||
| #pragma once | ||||
| #include <functional> | ||||
| #include <span> | ||||
| #include "common/hash.h" | ||||
| #include "video_core/rasterizer_cache/pixel_format.h" | ||||
| #include "video_core/rasterizer_cache/types.h" | ||||
| @@ -47,6 +48,14 @@ struct TextureCubeConfig { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class SurfaceParams; | ||||
|  | ||||
| void SwizzleTexture(const SurfaceParams& params, u32 flush_start, u32 flush_end, | ||||
|                     std::span<std::byte> source, std::span<std::byte> dest); | ||||
|  | ||||
| void UnswizzleTexture(const SurfaceParams& params, u32 load_start, u32 load_end, | ||||
|                       std::span<const std::byte> source, std::span<std::byte> dest); | ||||
|  | ||||
| [[nodiscard]] ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data); | ||||
|  | ||||
| [[nodiscard]] Aspect ToAspect(SurfaceType type); | ||||
|   | ||||
| @@ -2,10 +2,10 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <bit> | ||||
| #include "common/assert.h" | ||||
| #include "common/color.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/math_util.h" | ||||
| #include "common/swap.h" | ||||
| #include "common/vector_math.h" | ||||
| #include "video_core/regs_texturing.h" | ||||
| @@ -223,4 +223,23 @@ TextureInfo TextureInfo::FromPicaRegister(const TexturingRegs::TextureConfig& co | ||||
|     return info; | ||||
| } | ||||
|  | ||||
| void ConvertBGRToRGBA(std::span<const std::byte> source, std::span<std::byte> dest) { | ||||
|     u32 j = 0; | ||||
|     for (u32 i = 0; i < source.size(); i += 3) { | ||||
|         dest[j] = source[i + 2]; | ||||
|         dest[j + 1] = source[i + 1]; | ||||
|         dest[j + 2] = source[i]; | ||||
|         dest[j + 3] = std::byte{0xFF}; | ||||
|         j += 4; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ConvertABGRToRGBA(std::span<const std::byte> source, std::span<std::byte> dest) { | ||||
|     for (u32 i = 0; i < source.size(); i += 4) { | ||||
|         const u32 abgr = *reinterpret_cast<const u32*>(source.data() + i); | ||||
|         const u32 rgba = std::byteswap(abgr); | ||||
|         std::memcpy(dest.data() + i, &rgba, 4); | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace Pica::Texture | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <span> | ||||
| #include "common/common_types.h" | ||||
| #include "common/vector_math.h" | ||||
| #include "video_core/regs_texturing.h" | ||||
| @@ -55,4 +55,21 @@ Common::Vec4<u8> LookupTexture(const u8* source, unsigned int x, unsigned int y, | ||||
| Common::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int y, | ||||
|                                    const TextureInfo& info, bool disable_alpha); | ||||
|  | ||||
| /** | ||||
|  * Converts pixel data encoded in BGR format to RGBA | ||||
|  * | ||||
|  * @param source Span to the source pixel data | ||||
|  * @param dest Span to the destination pixel data | ||||
|  */ | ||||
| void ConvertBGRToRGBA(std::span<const std::byte> source, std::span<std::byte> dest); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Converts pixel data encoded in ABGR format to RGBA | ||||
|  * | ||||
|  * @param source Span to the source pixel data | ||||
|  * @param dest Span to the destination pixel data | ||||
|  */ | ||||
| void ConvertABGRToRGBA(std::span<const std::byte> source, std::span<std::byte> dest); | ||||
|  | ||||
| } // namespace Pica::Texture | ||||
|   | ||||
		Reference in New Issue
	
	Block a user