mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-16 12:36:59 +02:00
[vk, opengl] recognize and use ETC2 (if available) textures natively (#3237)
this makes it so VK and OGL backends map the NVIDIA's ETC2 into VK_FORMAT_ETC-whatever and GL_ETC-whatever remaps, instead of using the default fallback for AR8G8B8. in short, just make the ETC2 textures be submitted as ETC2 instead of being submit as A8R8G8B8. Signed-off-by: lizzie lizzie@eden-emu.dev Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3237 Reviewed-by: Ghost <> Reviewed-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
parent
2f0f8a979c
commit
4d49341918
6 changed files with 60 additions and 208 deletions
|
|
@ -217,6 +217,12 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with
|
|||
SURFACE_FORMAT_ELEM(VK_FORMAT_ASTC_6x5_UNORM_BLOCK, 0, ASTC_2D_6X5_UNORM) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_ASTC_6x5_SRGB_BLOCK, 0, ASTC_2D_6X5_SRGB) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 0, E5B9G9R9_FLOAT) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, 0, ETC2_RGB_UNORM) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, 0, ETC2_RGBA_UNORM) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, 0, ETC2_RGB_PTA_UNORM) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, 0, ETC2_RGB_SRGB) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, 0, ETC2_RGBA_SRGB) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, 0, ETC2_RGB_PTA_SRGB) \
|
||||
/* Depth formats */ \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_D32_SFLOAT, usage_attachable, D32_FLOAT) \
|
||||
SURFACE_FORMAT_ELEM(VK_FORMAT_D16_UNORM, usage_attachable, D16_UNORM) \
|
||||
|
|
@ -253,8 +259,8 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with
|
|||
break;
|
||||
}
|
||||
}
|
||||
// Transcode on hardware that doesn't support BCn natively
|
||||
if (!device.IsOptimalBcnSupported() && VideoCore::Surface::IsPixelFormatBCn(pixel_format)) {
|
||||
// Transcode on hardware that doesn't support BCn natively
|
||||
if (pixel_format == PixelFormat::BC4_SNORM) {
|
||||
tuple.format = VK_FORMAT_R8_SNORM;
|
||||
} else if (pixel_format == PixelFormat::BC4_UNORM) {
|
||||
|
|
@ -270,6 +276,9 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with
|
|||
} else {
|
||||
tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||
}
|
||||
} else if (!device.IsOptimalEtc2Supported() && VideoCore::Surface::IsPixelFormatETC2(pixel_format)) {
|
||||
// Transcode on hardware that doesn't support ETC2 natively
|
||||
tuple.format = is_srgb ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 : VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||
}
|
||||
bool const attachable = (tuple.usage & usage_attachable) != 0;
|
||||
bool const storage = (tuple.usage & usage_storage) != 0;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
|
|
@ -336,6 +336,20 @@ bool IsPixelFormatBCn(PixelFormat format) {
|
|||
}
|
||||
}
|
||||
|
||||
bool IsPixelFormatETC2(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PixelFormat::ETC2_RGB_UNORM:
|
||||
case PixelFormat::ETC2_RGBA_UNORM:
|
||||
case PixelFormat::ETC2_RGB_PTA_UNORM:
|
||||
case PixelFormat::ETC2_RGB_SRGB:
|
||||
case PixelFormat::ETC2_RGBA_SRGB:
|
||||
case PixelFormat::ETC2_RGB_PTA_SRGB:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPixelFormatSRGB(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PixelFormat::A8B8G8R8_SRGB:
|
||||
|
|
@ -344,6 +358,9 @@ bool IsPixelFormatSRGB(PixelFormat format) {
|
|||
case PixelFormat::BC2_SRGB:
|
||||
case PixelFormat::BC3_SRGB:
|
||||
case PixelFormat::BC7_SRGB:
|
||||
case PixelFormat::ETC2_RGB_SRGB:
|
||||
case PixelFormat::ETC2_RGBA_SRGB:
|
||||
case PixelFormat::ETC2_RGB_PTA_SRGB:
|
||||
case PixelFormat::ASTC_2D_4X4_SRGB:
|
||||
case PixelFormat::ASTC_2D_8X8_SRGB:
|
||||
case PixelFormat::ASTC_2D_8X5_SRGB:
|
||||
|
|
|
|||
|
|
@ -111,6 +111,12 @@ namespace VideoCore::Surface {
|
|||
PIXEL_FORMAT_ELEM(ASTC_2D_6X5_UNORM, 6, 5, 128) \
|
||||
PIXEL_FORMAT_ELEM(ASTC_2D_6X5_SRGB, 6, 5, 128) \
|
||||
PIXEL_FORMAT_ELEM(E5B9G9R9_FLOAT, 1, 1, 32) \
|
||||
PIXEL_FORMAT_ELEM(ETC2_RGB_UNORM, 4, 4, 64) \
|
||||
PIXEL_FORMAT_ELEM(ETC2_RGBA_UNORM, 4, 4, 128) \
|
||||
PIXEL_FORMAT_ELEM(ETC2_RGB_PTA_UNORM, 4, 4, 64) \
|
||||
PIXEL_FORMAT_ELEM(ETC2_RGB_SRGB, 4, 4, 64) \
|
||||
PIXEL_FORMAT_ELEM(ETC2_RGBA_SRGB, 4, 4, 128) \
|
||||
PIXEL_FORMAT_ELEM(ETC2_RGB_PTA_SRGB, 4, 4, 64) \
|
||||
/* Depth formats */ \
|
||||
PIXEL_FORMAT_ELEM(D32_FLOAT, 1, 1, 32) \
|
||||
PIXEL_FORMAT_ELEM(D16_UNORM, 1, 1, 16) \
|
||||
|
|
@ -181,8 +187,6 @@ constexpr u32 BitsPerBlock(PixelFormat format) noexcept {
|
|||
}
|
||||
}
|
||||
|
||||
#undef PIXEL_FORMAT_LIST
|
||||
|
||||
/// Returns the sizer in bytes of the specified pixel format
|
||||
constexpr u32 BytesPerBlock(PixelFormat pixel_format) {
|
||||
return BitsPerBlock(pixel_format) / CHAR_BIT;
|
||||
|
|
@ -198,6 +202,7 @@ SurfaceType GetFormatType(PixelFormat pixel_format);
|
|||
bool HasAlpha(PixelFormat pixel_format);
|
||||
bool IsPixelFormatASTC(PixelFormat format);
|
||||
bool IsPixelFormatBCn(PixelFormat format);
|
||||
bool IsPixelFormatETC2(PixelFormat format);
|
||||
bool IsPixelFormatSRGB(PixelFormat format);
|
||||
bool IsPixelFormatInteger(PixelFormat format);
|
||||
bool IsPixelFormatSignedInteger(PixelFormat format);
|
||||
|
|
|
|||
|
|
@ -191,6 +191,20 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red,
|
|||
return PixelFormat::BC6H_SFLOAT;
|
||||
case Hash(TextureFormat::BC6H_U16, FLOAT):
|
||||
return PixelFormat::BC6H_UFLOAT;
|
||||
/* ETC2 */
|
||||
case Hash(TextureFormat::ETC2_RGB, UNORM, LINEAR):
|
||||
return PixelFormat::ETC2_RGB_UNORM;
|
||||
case Hash(TextureFormat::ETC2_RGB_PTA, UNORM, LINEAR):
|
||||
return PixelFormat::ETC2_RGB_PTA_UNORM;
|
||||
case Hash(TextureFormat::ETC2_RGBA, UNORM, LINEAR):
|
||||
return PixelFormat::ETC2_RGBA_UNORM;
|
||||
case Hash(TextureFormat::ETC2_RGB, UNORM, SRGB):
|
||||
return PixelFormat::ETC2_RGB_SRGB;
|
||||
case Hash(TextureFormat::ETC2_RGB_PTA, UNORM, SRGB):
|
||||
return PixelFormat::ETC2_RGB_PTA_SRGB;
|
||||
case Hash(TextureFormat::ETC2_RGBA, UNORM, SRGB):
|
||||
return PixelFormat::ETC2_RGBA_SRGB;
|
||||
/* ASTC */
|
||||
case Hash(TextureFormat::ASTC_2D_4X4, UNORM, LINEAR):
|
||||
return PixelFormat::ASTC_2D_4X4_UNORM;
|
||||
case Hash(TextureFormat::ASTC_2D_4X4, UNORM, SRGB):
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -17,210 +20,9 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str
|
|||
using VideoCore::Surface::PixelFormat;
|
||||
const string_view name = [format] {
|
||||
switch (format) {
|
||||
case PixelFormat::A8B8G8R8_UNORM:
|
||||
return "A8B8G8R8_UNORM";
|
||||
case PixelFormat::A8B8G8R8_SNORM:
|
||||
return "A8B8G8R8_SNORM";
|
||||
case PixelFormat::A8B8G8R8_SINT:
|
||||
return "A8B8G8R8_SINT";
|
||||
case PixelFormat::A8B8G8R8_UINT:
|
||||
return "A8B8G8R8_UINT";
|
||||
case PixelFormat::R5G6B5_UNORM:
|
||||
return "R5G6B5_UNORM";
|
||||
case PixelFormat::B5G6R5_UNORM:
|
||||
return "B5G6R5_UNORM";
|
||||
case PixelFormat::A1R5G5B5_UNORM:
|
||||
return "A1R5G5B5_UNORM";
|
||||
case PixelFormat::A2B10G10R10_UNORM:
|
||||
return "A2B10G10R10_UNORM";
|
||||
case PixelFormat::A2B10G10R10_UINT:
|
||||
return "A2B10G10R10_UINT";
|
||||
case PixelFormat::A2R10G10B10_UNORM:
|
||||
return "A2R10G10B10_UNORM";
|
||||
case PixelFormat::A1B5G5R5_UNORM:
|
||||
return "A1B5G5R5_UNORM";
|
||||
case PixelFormat::A5B5G5R1_UNORM:
|
||||
return "A5B5G5R1_UNORM";
|
||||
case PixelFormat::R8_UNORM:
|
||||
return "R8_UNORM";
|
||||
case PixelFormat::R8_SNORM:
|
||||
return "R8_SNORM";
|
||||
case PixelFormat::R8_SINT:
|
||||
return "R8_SINT";
|
||||
case PixelFormat::R8_UINT:
|
||||
return "R8_UINT";
|
||||
case PixelFormat::R16G16B16A16_FLOAT:
|
||||
return "R16G16B16A16_FLOAT";
|
||||
case PixelFormat::R16G16B16A16_UNORM:
|
||||
return "R16G16B16A16_UNORM";
|
||||
case PixelFormat::R16G16B16A16_SNORM:
|
||||
return "R16G16B16A16_SNORM";
|
||||
case PixelFormat::R16G16B16A16_SINT:
|
||||
return "R16G16B16A16_SINT";
|
||||
case PixelFormat::R16G16B16A16_UINT:
|
||||
return "R16G16B16A16_UINT";
|
||||
case PixelFormat::B10G11R11_FLOAT:
|
||||
return "B10G11R11_FLOAT";
|
||||
case PixelFormat::R32G32B32A32_UINT:
|
||||
return "R32G32B32A32_UINT";
|
||||
case PixelFormat::BC1_RGBA_UNORM:
|
||||
return "BC1_RGBA_UNORM";
|
||||
case PixelFormat::BC2_UNORM:
|
||||
return "BC2_UNORM";
|
||||
case PixelFormat::BC3_UNORM:
|
||||
return "BC3_UNORM";
|
||||
case PixelFormat::BC4_UNORM:
|
||||
return "BC4_UNORM";
|
||||
case PixelFormat::BC4_SNORM:
|
||||
return "BC4_SNORM";
|
||||
case PixelFormat::BC5_UNORM:
|
||||
return "BC5_UNORM";
|
||||
case PixelFormat::BC5_SNORM:
|
||||
return "BC5_SNORM";
|
||||
case PixelFormat::BC7_UNORM:
|
||||
return "BC7_UNORM";
|
||||
case PixelFormat::BC6H_UFLOAT:
|
||||
return "BC6H_UFLOAT";
|
||||
case PixelFormat::BC6H_SFLOAT:
|
||||
return "BC6H_SFLOAT";
|
||||
case PixelFormat::ASTC_2D_4X4_UNORM:
|
||||
return "ASTC_2D_4X4_UNORM";
|
||||
case PixelFormat::B8G8R8A8_UNORM:
|
||||
return "B8G8R8A8_UNORM";
|
||||
case PixelFormat::R32G32B32A32_FLOAT:
|
||||
return "R32G32B32A32_FLOAT";
|
||||
case PixelFormat::R32G32B32A32_SINT:
|
||||
return "R32G32B32A32_SINT";
|
||||
case PixelFormat::R32G32_FLOAT:
|
||||
return "R32G32_FLOAT";
|
||||
case PixelFormat::R32G32_SINT:
|
||||
return "R32G32_SINT";
|
||||
case PixelFormat::R32_FLOAT:
|
||||
return "R32_FLOAT";
|
||||
case PixelFormat::R16_FLOAT:
|
||||
return "R16_FLOAT";
|
||||
case PixelFormat::R16_UNORM:
|
||||
return "R16_UNORM";
|
||||
case PixelFormat::R16_SNORM:
|
||||
return "R16_SNORM";
|
||||
case PixelFormat::R16_UINT:
|
||||
return "R16_UINT";
|
||||
case PixelFormat::R16_SINT:
|
||||
return "R16_SINT";
|
||||
case PixelFormat::R16G16_UNORM:
|
||||
return "R16G16_UNORM";
|
||||
case PixelFormat::R16G16_FLOAT:
|
||||
return "R16G16_FLOAT";
|
||||
case PixelFormat::R16G16_UINT:
|
||||
return "R16G16_UINT";
|
||||
case PixelFormat::R16G16_SINT:
|
||||
return "R16G16_SINT";
|
||||
case PixelFormat::R16G16_SNORM:
|
||||
return "R16G16_SNORM";
|
||||
case PixelFormat::R32G32B32_FLOAT:
|
||||
return "R32G32B32_FLOAT";
|
||||
case PixelFormat::A8B8G8R8_SRGB:
|
||||
return "A8B8G8R8_SRGB";
|
||||
case PixelFormat::R8G8_UNORM:
|
||||
return "R8G8_UNORM";
|
||||
case PixelFormat::R8G8_SNORM:
|
||||
return "R8G8_SNORM";
|
||||
case PixelFormat::R8G8_SINT:
|
||||
return "R8G8_SINT";
|
||||
case PixelFormat::R8G8_UINT:
|
||||
return "R8G8_UINT";
|
||||
case PixelFormat::R32G32_UINT:
|
||||
return "R32G32_UINT";
|
||||
case PixelFormat::R16G16B16X16_FLOAT:
|
||||
return "R16G16B16X16_FLOAT";
|
||||
case PixelFormat::R32_UINT:
|
||||
return "R32_UINT";
|
||||
case PixelFormat::R32_SINT:
|
||||
return "R32_SINT";
|
||||
case PixelFormat::ASTC_2D_8X8_UNORM:
|
||||
return "ASTC_2D_8X8_UNORM";
|
||||
case PixelFormat::ASTC_2D_8X5_UNORM:
|
||||
return "ASTC_2D_8X5_UNORM";
|
||||
case PixelFormat::ASTC_2D_5X4_UNORM:
|
||||
return "ASTC_2D_5X4_UNORM";
|
||||
case PixelFormat::B8G8R8A8_SRGB:
|
||||
return "B8G8R8A8_SRGB";
|
||||
case PixelFormat::BC1_RGBA_SRGB:
|
||||
return "BC1_RGBA_SRGB";
|
||||
case PixelFormat::BC2_SRGB:
|
||||
return "BC2_SRGB";
|
||||
case PixelFormat::BC3_SRGB:
|
||||
return "BC3_SRGB";
|
||||
case PixelFormat::BC7_SRGB:
|
||||
return "BC7_SRGB";
|
||||
case PixelFormat::A4B4G4R4_UNORM:
|
||||
return "A4B4G4R4_UNORM";
|
||||
case PixelFormat::G4R4_UNORM:
|
||||
return "G4R4_UNORM";
|
||||
case PixelFormat::ASTC_2D_4X4_SRGB:
|
||||
return "ASTC_2D_4X4_SRGB";
|
||||
case PixelFormat::ASTC_2D_8X8_SRGB:
|
||||
return "ASTC_2D_8X8_SRGB";
|
||||
case PixelFormat::ASTC_2D_8X5_SRGB:
|
||||
return "ASTC_2D_8X5_SRGB";
|
||||
case PixelFormat::ASTC_2D_5X4_SRGB:
|
||||
return "ASTC_2D_5X4_SRGB";
|
||||
case PixelFormat::ASTC_2D_5X5_UNORM:
|
||||
return "ASTC_2D_5X5_UNORM";
|
||||
case PixelFormat::ASTC_2D_5X5_SRGB:
|
||||
return "ASTC_2D_5X5_SRGB";
|
||||
case PixelFormat::ASTC_2D_10X8_UNORM:
|
||||
return "ASTC_2D_10X8_UNORM";
|
||||
case PixelFormat::ASTC_2D_10X8_SRGB:
|
||||
return "ASTC_2D_10X8_SRGB";
|
||||
case PixelFormat::ASTC_2D_6X6_UNORM:
|
||||
return "ASTC_2D_6X6_UNORM";
|
||||
case PixelFormat::ASTC_2D_6X6_SRGB:
|
||||
return "ASTC_2D_6X6_SRGB";
|
||||
case PixelFormat::ASTC_2D_10X6_UNORM:
|
||||
return "ASTC_2D_10X6_UNORM";
|
||||
case PixelFormat::ASTC_2D_10X6_SRGB:
|
||||
return "ASTC_2D_10X6_SRGB";
|
||||
case PixelFormat::ASTC_2D_10X5_UNORM:
|
||||
return "ASTC_2D_10X5_UNORM";
|
||||
case PixelFormat::ASTC_2D_10X5_SRGB:
|
||||
return "ASTC_2D_10X5_SRGB";
|
||||
case PixelFormat::ASTC_2D_10X10_UNORM:
|
||||
return "ASTC_2D_10X10_UNORM";
|
||||
case PixelFormat::ASTC_2D_10X10_SRGB:
|
||||
return "ASTC_2D_10X10_SRGB";
|
||||
case PixelFormat::ASTC_2D_12X10_UNORM:
|
||||
return "ASTC_2D_12X10_UNORM";
|
||||
case PixelFormat::ASTC_2D_12X10_SRGB:
|
||||
return "ASTC_2D_12X10_SRGB";
|
||||
case PixelFormat::ASTC_2D_12X12_UNORM:
|
||||
return "ASTC_2D_12X12_UNORM";
|
||||
case PixelFormat::ASTC_2D_12X12_SRGB:
|
||||
return "ASTC_2D_12X12_SRGB";
|
||||
case PixelFormat::ASTC_2D_8X6_UNORM:
|
||||
return "ASTC_2D_8X6_UNORM";
|
||||
case PixelFormat::ASTC_2D_8X6_SRGB:
|
||||
return "ASTC_2D_8X6_SRGB";
|
||||
case PixelFormat::ASTC_2D_6X5_UNORM:
|
||||
return "ASTC_2D_6X5_UNORM";
|
||||
case PixelFormat::ASTC_2D_6X5_SRGB:
|
||||
return "ASTC_2D_6X5_SRGB";
|
||||
case PixelFormat::E5B9G9R9_FLOAT:
|
||||
return "E5B9G9R9_FLOAT";
|
||||
case PixelFormat::D32_FLOAT:
|
||||
return "D32_FLOAT";
|
||||
case PixelFormat::D16_UNORM:
|
||||
return "D16_UNORM";
|
||||
case PixelFormat::X8_D24_UNORM:
|
||||
return "X8_D24_UNORM";
|
||||
case PixelFormat::S8_UINT:
|
||||
return "S8_UINT";
|
||||
case PixelFormat::D24_UNORM_S8_UINT:
|
||||
return "D24_UNORM_S8_UINT";
|
||||
case PixelFormat::S8_UINT_D24_UNORM:
|
||||
return "S8_UINT_D24_UNORM";
|
||||
case PixelFormat::D32_FLOAT_S8_UINT:
|
||||
return "D32_FLOAT_S8_UINT";
|
||||
#define PIXEL_FORMAT_ELEM(NAME, ...) case PixelFormat::NAME: return #NAME;
|
||||
PIXEL_FORMAT_LIST
|
||||
#undef PIXEL_FORMAT_ELEM
|
||||
case PixelFormat::MaxDepthStencilFormat:
|
||||
case PixelFormat::Invalid:
|
||||
return "Invalid";
|
||||
|
|
|
|||
|
|
@ -363,6 +363,11 @@ public:
|
|||
return features.features.textureCompressionBC;
|
||||
}
|
||||
|
||||
/// Returns true if ETC2 is natively supported.
|
||||
bool IsOptimalEtc2Supported() const {
|
||||
return features.features.textureCompressionETC2;
|
||||
}
|
||||
|
||||
/// Returns true if descriptor aliasing is natively supported.
|
||||
bool IsDescriptorAliasingSupported() const {
|
||||
return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue