From 71ebc3e90da9882139d2a5695ca1ed59ea77e94f Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 19 Mar 2018 18:00:29 -0500 Subject: GPU: Preliminary work for texture decoding. --- src/video_core/textures/decoders.cpp | 14 +++++++++ src/video_core/textures/decoders.h | 20 +++++++++++++ src/video_core/textures/texture.h | 57 ++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/video_core/textures/decoders.cpp create mode 100644 src/video_core/textures/decoders.h create mode 100644 src/video_core/textures/texture.h (limited to 'src/video_core/textures') diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp new file mode 100644 index 000000000..705e2e066 --- /dev/null +++ b/src/video_core/textures/decoders.cpp @@ -0,0 +1,14 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "video_core/textures/decoders.h" + +namespace Tegra { +namespace Texture { + +std::vector DecodeTexture(VAddr address, TextureFormat format, u32 width, u32 height) { + return {}; +} +} +} // namespace Tegra diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h new file mode 100644 index 000000000..e0d55600e --- /dev/null +++ b/src/video_core/textures/decoders.h @@ -0,0 +1,20 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/common_types.h" +#include "video_core/textures/texture.h" + +namespace Tegra { +namespace Texture { + +/** + * Decodes a swizzled texture into a RGBA8888 texture. + */ +std::vector DecodeTexture(VAddr address, TextureFormat format, u32 width, u32 height); + +} // namespace Texture +} // namespace Tegra diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h new file mode 100644 index 000000000..3306d2ab2 --- /dev/null +++ b/src/video_core/textures/texture.h @@ -0,0 +1,57 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "video_core/memory_manager.h" + +namespace Tegra { +namespace Texture { + +enum class TextureFormat : u32 { + DXT1 = 0x24, +}; + +union TextureHandle { + u32 raw; + BitField<0, 20, u32> tic_id; + BitField<20, 12, u32> tsc_id; +}; + +struct TICEntry { + union { + u32 raw; + BitField<0, 7, TextureFormat> format; + BitField<7, 3, u32> r_type; + BitField<10, 3, u32> g_type; + BitField<13, 3, u32> b_type; + BitField<16, 3, u32> a_type; + }; + u32 address_low; + u16 address_high; + INSERT_PADDING_BYTES(6); + u16 width_minus_1; + INSERT_PADDING_BYTES(2); + u16 height_minus_1; + INSERT_PADDING_BYTES(10); + + GPUVAddr Address() const { + return static_cast((static_cast(address_high) << 32) | address_low); + } + + u32 Width() const { + return width_minus_1 + 1; + } + + u32 Height() const { + return height_minus_1 + 1; + } +}; +static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size"); + +} // namespace Texture +} // namespace Tegra -- cgit v1.2.3 From 1b8d798835c2d39c2867f53d8dcacdc7d0ba0d15 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 22 Mar 2018 15:17:10 -0500 Subject: GPU: Added a method to unswizzle a texture without decoding it. Allow unswizzling of DXT1 textures. --- src/video_core/textures/decoders.cpp | 84 +++++++++++++++++++++++++++++++++++- src/video_core/textures/decoders.h | 10 ++++- src/video_core/textures/texture.h | 4 ++ 3 files changed, 94 insertions(+), 4 deletions(-) (limited to 'src/video_core/textures') diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 705e2e066..300267209 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -2,13 +2,93 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include "common/assert.h" #include "video_core/textures/decoders.h" +#include "video_core/textures/texture.h" namespace Tegra { namespace Texture { -std::vector DecodeTexture(VAddr address, TextureFormat format, u32 width, u32 height) { - return {}; +/** + * Calculates the offset of an (x, y) position within a swizzled texture. + * Taken from the Tegra X1 TRM. + */ +static u32 GetSwizzleOffset(u32 x, u32 y, u32 image_width, u32 bytes_per_pixel, u32 block_height) { + u32 image_width_in_gobs = image_width * bytes_per_pixel / 64; + u32 GOB_address = 0 + (y / (8 * block_height)) * 512 * block_height * image_width_in_gobs + + (x * bytes_per_pixel / 64) * 512 * block_height + + (y % (8 * block_height) / 8) * 512; + x *= bytes_per_pixel; + u32 address = GOB_address + ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 + + (y % 2) * 16 + (x % 16); + + return address; } + +static void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel, + u8* swizzled_data, u8* unswizzled_data, bool unswizzle, + u32 block_height) { + u8* data_ptrs[2]; + for (unsigned y = 0; y < height; ++y) { + for (unsigned x = 0; x < width; ++x) { + u32 swizzle_offset = GetSwizzleOffset(x, y, width, bytes_per_pixel, block_height); + u32 pixel_index = (x + y * width) * out_bytes_per_pixel; + + data_ptrs[unswizzle] = swizzled_data + swizzle_offset; + data_ptrs[!unswizzle] = &unswizzled_data[pixel_index]; + + std::memcpy(data_ptrs[0], data_ptrs[1], bytes_per_pixel); + } + } } + +u32 BytesPerPixel(TextureFormat format) { + switch (format) { + case TextureFormat::DXT1: + // In this case a 'pixel' actually refers to a 4x4 tile. + return 8; + default: + UNIMPLEMENTED_MSG("Format not implemented"); + break; + } +} + +std::vector UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) { + u8* data = Memory::GetPointer(address); + u32 bytes_per_pixel = BytesPerPixel(format); + + static constexpr u32 DefaultBlockHeight = 16; + + std::vector unswizzled_data(width * height * bytes_per_pixel); + + switch (format) { + case TextureFormat::DXT1: + // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values. + CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, + unswizzled_data.data(), true, DefaultBlockHeight); + break; + default: + UNIMPLEMENTED_MSG("Format not implemented"); + break; + } + + return unswizzled_data; +} + +std::vector DecodeTexture(const std::vector& texture_data, TextureFormat format, u32 width, + u32 height) { + std::vector rgba_data; + + // TODO(Subv): Implement. + switch (format) { + default: + UNIMPLEMENTED_MSG("Format not implemented"); + break; + } + + return rgba_data; +} + +} // namespace Texture } // namespace Tegra diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index e0d55600e..0c21694ff 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h @@ -12,9 +12,15 @@ namespace Tegra { namespace Texture { /** - * Decodes a swizzled texture into a RGBA8888 texture. + * Unswizzles a swizzled texture without changing its format. */ -std::vector DecodeTexture(VAddr address, TextureFormat format, u32 width, u32 height); +std::vector UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height); + +/** + * Decodes an unswizzled texture into a A8R8G8B8 texture. + */ +std::vector DecodeTexture(const std::vector& texture_data, TextureFormat format, u32 width, + u32 height); } // namespace Texture } // namespace Tegra diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index 3306d2ab2..d969bcdd9 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h @@ -13,6 +13,7 @@ namespace Tegra { namespace Texture { enum class TextureFormat : u32 { + A8R8G8B8 = 8, DXT1 = 0x24, }; @@ -53,5 +54,8 @@ struct TICEntry { }; static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size"); +/// Returns the number of bytes per pixel of the input texture format. +u32 BytesPerPixel(TextureFormat format); + } // namespace Texture } // namespace Tegra -- cgit v1.2.3 From 39e60cfeb10ef317521ff1685df3d265d2c9d5ef Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 22 Mar 2018 16:40:11 -0500 Subject: Frontend: Updated the surface view debug widget to work with Maxwell surfaces. --- src/video_core/textures/decoders.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/video_core/textures') diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 300267209..2e87281eb 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -48,6 +48,8 @@ u32 BytesPerPixel(TextureFormat format) { case TextureFormat::DXT1: // In this case a 'pixel' actually refers to a 4x4 tile. return 8; + case TextureFormat::A8R8G8B8: + return 4; default: UNIMPLEMENTED_MSG("Format not implemented"); break; @@ -68,6 +70,10 @@ std::vector UnswizzleTexture(VAddr address, TextureFormat format, u32 width, CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, unswizzled_data.data(), true, DefaultBlockHeight); break; + case TextureFormat::A8R8G8B8: + CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, + unswizzled_data.data(), true, DefaultBlockHeight); + break; default: UNIMPLEMENTED_MSG("Format not implemented"); break; @@ -82,6 +88,11 @@ std::vector DecodeTexture(const std::vector& texture_data, TextureFormat // TODO(Subv): Implement. switch (format) { + case TextureFormat::DXT1: + case TextureFormat::A8R8G8B8: + // TODO(Subv): For the time being just forward the same data without any decoding. + rgba_data = texture_data; + break; default: UNIMPLEMENTED_MSG("Format not implemented"); break; -- cgit v1.2.3