textures: Refactor out for Texture/Depth FormatFromPixelFormat.
This commit is contained in:
parent
6828c25498
commit
3a67876252
5 changed files with 31 additions and 181 deletions
|
@ -183,6 +183,21 @@ MathUtil::Rectangle<u32> SurfaceParams::GetRect() const {
|
|||
return {0, actual_height, width, 0};
|
||||
}
|
||||
|
||||
/// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN
|
||||
static bool IsFormatBCn(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PixelFormat::DXT1:
|
||||
case PixelFormat::DXT23:
|
||||
case PixelFormat::DXT45:
|
||||
case PixelFormat::DXN1:
|
||||
case PixelFormat::DXN2SNORM:
|
||||
case PixelFormat::DXN2UNORM:
|
||||
case PixelFormat::BC7U:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <bool morton_to_gl, PixelFormat format>
|
||||
void MortonCopy(u32 stride, u32 block_height, u32 height, std::vector<u8>& gl_buffer,
|
||||
Tegra::GPUVAddr addr) {
|
||||
|
@ -191,16 +206,12 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, std::vector<u8>& gl_bu
|
|||
const auto& gpu = Core::System::GetInstance().GPU();
|
||||
|
||||
if (morton_to_gl) {
|
||||
std::vector<u8> data;
|
||||
if (SurfaceParams::GetFormatType(format) == SurfaceType::ColorTexture) {
|
||||
data = Tegra::Texture::UnswizzleTexture(
|
||||
*gpu.memory_manager->GpuToCpuAddress(addr),
|
||||
SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height);
|
||||
} else {
|
||||
data = Tegra::Texture::UnswizzleDepthTexture(
|
||||
*gpu.memory_manager->GpuToCpuAddress(addr),
|
||||
SurfaceParams::DepthFormatFromPixelFormat(format), stride, height, block_height);
|
||||
}
|
||||
// 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 std::vector<u8> data =
|
||||
Tegra::Texture::UnswizzleTexture(*gpu.memory_manager->GpuToCpuAddress(addr), tile_size,
|
||||
bytes_per_pixel, stride, height, block_height);
|
||||
const size_t size_to_copy{std::min(gl_buffer.size(), data.size())};
|
||||
gl_buffer.assign(data.begin(), data.begin() + size_to_copy);
|
||||
} else {
|
||||
|
|
|
@ -348,92 +348,6 @@ struct SurfaceParams {
|
|||
}
|
||||
}
|
||||
|
||||
static Tegra::Texture::TextureFormat TextureFormatFromPixelFormat(PixelFormat format) {
|
||||
// TODO(Subv): Properly implement this
|
||||
switch (format) {
|
||||
case PixelFormat::ABGR8:
|
||||
case PixelFormat::SRGBA8:
|
||||
return Tegra::Texture::TextureFormat::A8R8G8B8;
|
||||
case PixelFormat::B5G6R5:
|
||||
return Tegra::Texture::TextureFormat::B5G6R5;
|
||||
case PixelFormat::A2B10G10R10:
|
||||
return Tegra::Texture::TextureFormat::A2B10G10R10;
|
||||
case PixelFormat::A1B5G5R5:
|
||||
return Tegra::Texture::TextureFormat::A1B5G5R5;
|
||||
case PixelFormat::R8:
|
||||
return Tegra::Texture::TextureFormat::R8;
|
||||
case PixelFormat::G8R8:
|
||||
return Tegra::Texture::TextureFormat::G8R8;
|
||||
case PixelFormat::RGBA16F:
|
||||
return Tegra::Texture::TextureFormat::R16_G16_B16_A16;
|
||||
case PixelFormat::R11FG11FB10F:
|
||||
return Tegra::Texture::TextureFormat::BF10GF11RF11;
|
||||
case PixelFormat::RGBA32UI:
|
||||
return Tegra::Texture::TextureFormat::R32_G32_B32_A32;
|
||||
case PixelFormat::DXT1:
|
||||
return Tegra::Texture::TextureFormat::DXT1;
|
||||
case PixelFormat::DXT23:
|
||||
return Tegra::Texture::TextureFormat::DXT23;
|
||||
case PixelFormat::DXT45:
|
||||
return Tegra::Texture::TextureFormat::DXT45;
|
||||
case PixelFormat::DXN1:
|
||||
return Tegra::Texture::TextureFormat::DXN1;
|
||||
case PixelFormat::DXN2UNORM:
|
||||
case PixelFormat::DXN2SNORM:
|
||||
return Tegra::Texture::TextureFormat::DXN2;
|
||||
case PixelFormat::BC7U:
|
||||
return Tegra::Texture::TextureFormat::BC7U;
|
||||
case PixelFormat::ASTC_2D_4X4:
|
||||
return Tegra::Texture::TextureFormat::ASTC_2D_4X4;
|
||||
case PixelFormat::BGRA8:
|
||||
// TODO(bunnei): This is fine for unswizzling (since we just need the right component
|
||||
// sizes), but could be a bug if we used this function in different ways.
|
||||
return Tegra::Texture::TextureFormat::A8R8G8B8;
|
||||
case PixelFormat::RGBA32F:
|
||||
return Tegra::Texture::TextureFormat::R32_G32_B32_A32;
|
||||
case PixelFormat::RGB32F:
|
||||
return Tegra::Texture::TextureFormat::R32_G32_B32;
|
||||
case PixelFormat::RG32F:
|
||||
return Tegra::Texture::TextureFormat::R32_G32;
|
||||
case PixelFormat::R32F:
|
||||
return Tegra::Texture::TextureFormat::R32;
|
||||
case PixelFormat::R16F:
|
||||
case PixelFormat::R16UNORM:
|
||||
return Tegra::Texture::TextureFormat::R16;
|
||||
case PixelFormat::Z32F:
|
||||
return Tegra::Texture::TextureFormat::ZF32;
|
||||
case PixelFormat::Z24S8:
|
||||
return Tegra::Texture::TextureFormat::Z24S8;
|
||||
case PixelFormat::RG16F:
|
||||
case PixelFormat::RG16:
|
||||
case PixelFormat::RG16UI:
|
||||
case PixelFormat::RG16I:
|
||||
case PixelFormat::RG16S:
|
||||
return Tegra::Texture::TextureFormat::R16_G16;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
static Tegra::DepthFormat DepthFormatFromPixelFormat(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PixelFormat::S8Z24:
|
||||
return Tegra::DepthFormat::S8_Z24_UNORM;
|
||||
case PixelFormat::Z24S8:
|
||||
return Tegra::DepthFormat::Z24_S8_UNORM;
|
||||
case PixelFormat::Z32F:
|
||||
return Tegra::DepthFormat::Z32_FLOAT;
|
||||
case PixelFormat::Z16:
|
||||
return Tegra::DepthFormat::Z16_UNORM;
|
||||
case PixelFormat::Z32FS8:
|
||||
return Tegra::DepthFormat::Z32_S8_X24_FLOAT;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) {
|
||||
// TODO(Subv): Implement more component types
|
||||
switch (type) {
|
||||
|
|
|
@ -86,88 +86,11 @@ u32 BytesPerPixel(TextureFormat format) {
|
|||
}
|
||||
}
|
||||
|
||||
static u32 DepthBytesPerPixel(DepthFormat format) {
|
||||
switch (format) {
|
||||
case DepthFormat::Z16_UNORM:
|
||||
return 2;
|
||||
case DepthFormat::S8_Z24_UNORM:
|
||||
case DepthFormat::Z24_S8_UNORM:
|
||||
case DepthFormat::Z32_FLOAT:
|
||||
return 4;
|
||||
case DepthFormat::Z32_S8_X24_FLOAT:
|
||||
return 8;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Format not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
|
||||
u32 block_height) {
|
||||
u8* data = Memory::GetPointer(address);
|
||||
u32 bytes_per_pixel = BytesPerPixel(format);
|
||||
|
||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
|
||||
u32 height, u32 block_height) {
|
||||
std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
|
||||
|
||||
switch (format) {
|
||||
case TextureFormat::DXT1:
|
||||
case TextureFormat::DXT23:
|
||||
case TextureFormat::DXT45:
|
||||
case TextureFormat::DXN1:
|
||||
case TextureFormat::DXN2:
|
||||
case TextureFormat::BC7U:
|
||||
// In the DXT and DXN formats, 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, block_height);
|
||||
break;
|
||||
case TextureFormat::A8R8G8B8:
|
||||
case TextureFormat::A2B10G10R10:
|
||||
case TextureFormat::A1B5G5R5:
|
||||
case TextureFormat::B5G6R5:
|
||||
case TextureFormat::R8:
|
||||
case TextureFormat::G8R8:
|
||||
case TextureFormat::R16_G16_B16_A16:
|
||||
case TextureFormat::R32_G32_B32_A32:
|
||||
case TextureFormat::R32_G32:
|
||||
case TextureFormat::R32:
|
||||
case TextureFormat::R16:
|
||||
case TextureFormat::R16_G16:
|
||||
case TextureFormat::BF10GF11RF11:
|
||||
case TextureFormat::ASTC_2D_4X4:
|
||||
case TextureFormat::R32_G32_B32:
|
||||
CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
|
||||
unswizzled_data.data(), true, block_height);
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Format not implemented");
|
||||
break;
|
||||
}
|
||||
|
||||
return unswizzled_data;
|
||||
}
|
||||
|
||||
std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 width, u32 height,
|
||||
u32 block_height) {
|
||||
u8* data = Memory::GetPointer(address);
|
||||
u32 bytes_per_pixel = DepthBytesPerPixel(format);
|
||||
|
||||
std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
|
||||
|
||||
switch (format) {
|
||||
case DepthFormat::Z16_UNORM:
|
||||
case DepthFormat::S8_Z24_UNORM:
|
||||
case DepthFormat::Z24_S8_UNORM:
|
||||
case DepthFormat::Z32_FLOAT:
|
||||
case DepthFormat::Z32_S8_X24_FLOAT:
|
||||
CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
|
||||
unswizzled_data.data(), true, block_height);
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Format not implemented");
|
||||
break;
|
||||
}
|
||||
|
||||
CopySwizzledData(width / tile_size, height / tile_size, bytes_per_pixel, bytes_per_pixel,
|
||||
Memory::GetPointer(address), unswizzled_data.data(), true, block_height);
|
||||
return unswizzled_data;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace Tegra::Texture {
|
|||
/**
|
||||
* Unswizzles a swizzled texture without changing its format.
|
||||
*/
|
||||
std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
|
||||
u32 block_height = TICEntry::DefaultBlockHeight);
|
||||
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
|
||||
u32 height, u32 block_height = TICEntry::DefaultBlockHeight);
|
||||
|
||||
/**
|
||||
* Unswizzles a swizzled depth texture without changing its format.
|
||||
|
|
|
@ -383,8 +383,10 @@ void GraphicsSurfaceWidget::OnUpdate() {
|
|||
QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
|
||||
boost::optional<VAddr> address = gpu.memory_manager->GpuToCpuAddress(surface_address);
|
||||
|
||||
auto unswizzled_data =
|
||||
Tegra::Texture::UnswizzleTexture(*address, surface_format, surface_width, surface_height);
|
||||
// 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);
|
||||
|
||||
auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,
|
||||
surface_width, surface_height);
|
||||
|
|
Loading…
Reference in a new issue