From 5cd6f7d6c0c661c213e08002b25b018b57ed7cf1 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 9 Feb 2026 22:59:35 +0000 Subject: [PATCH] [vk] Fix F32/U32 missing conversions where the format is A8R8G8B8_UINT and vk requires the format to actually be inbdexed by an integer composite op (texel fetch) Signed-off-by: lizzie --- .../spirv/emit_spirv_context_get_set.cpp | 21 +- .../backend/spirv/emit_spirv_image.cpp | 49 +-- .../backend/spirv/spirv_emit_context.cpp | 26 +- .../backend/spirv/spirv_emit_context.h | 5 +- src/shader_recompiler/ir_opt/texture_pass.cpp | 15 +- src/shader_recompiler/shader_info.h | 2 + src/video_core/shader_environment.cpp | 13 +- src/video_core/surface.cpp | 68 ++-- .../texture_cache/format_lookup_table.cpp | 350 ++++++------------ 9 files changed, 218 insertions(+), 331 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index db11def7b2..9f98ae0189 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -142,15 +142,20 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, const auto is_float = UniformDefinitions::IsFloat(member_ptr); const auto num_elements = UniformDefinitions::NumElements(member_ptr); - const std::array zero_vec{ - is_float ? ctx.Const(0.0f) : ctx.Const(0u), - is_float ? ctx.Const(0.0f) : ctx.Const(0u), - is_float ? ctx.Const(0.0f) : ctx.Const(0u), - is_float ? ctx.Const(0.0f) : ctx.Const(0u), - }; const Id cond = ctx.OpULessThanEqual(ctx.TypeBool(), buffer_offset, ctx.Const(0xFFFFu)); - const Id zero = ctx.OpCompositeConstruct(result_type, std::span(zero_vec.data(), num_elements)); - return ctx.OpSelect(result_type, cond, val, zero); + if (num_elements > 1) { + const std::array zero_vec{ + is_float ? ctx.Const(0.0f) : ctx.Const(0u), + is_float ? ctx.Const(0.0f) : ctx.Const(0u), + is_float ? ctx.Const(0.0f) : ctx.Const(0u), + is_float ? ctx.Const(0.0f) : ctx.Const(0u), + }; + const Id zero = ctx.OpCompositeConstruct(result_type, std::span(zero_vec.data(), num_elements)); + return ctx.OpSelect(result_type, cond, val, zero); + } else { + const Id zero = is_float ? ctx.Const(0.0f) : ctx.Const(0u); + return ctx.OpSelect(result_type, cond, val, zero); + } } Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index c07a778958..8bb2ff77a1 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -11,6 +11,7 @@ #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h" #include "shader_recompiler/frontend/ir/modifiers.h" +#include "shader_recompiler/shader_info.h" namespace Shader::Backend::SPIRV { namespace { @@ -70,8 +71,7 @@ public: } } - explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives, - u32 num_derivatives, const IR::Value& offset, Id lod_clamp) { + explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives, u32 num_derivatives, const IR::Value& offset, Id lod_clamp) { if (!Sirit::ValidId(derivatives)) { throw LogicError("Derivatives must be present"); } @@ -81,10 +81,8 @@ public: deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivatives, i * 2)); deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivatives, i * 2 + 1)); } - const Id derivatives_X{ctx.OpCompositeConstruct( - ctx.F32[num_derivatives], std::span{deriv_x_accum.data(), deriv_x_accum.size()})}; - const Id derivatives_Y{ctx.OpCompositeConstruct( - ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; + const Id derivatives_X{ctx.OpCompositeConstruct(ctx.F32[num_derivatives], std::span{deriv_x_accum.data(), deriv_x_accum.size()})}; + const Id derivatives_Y{ctx.OpCompositeConstruct(ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y); AddOffset(ctx, offset, ImageGradientOffsetAllowed); if (has_lod_clamp) { @@ -197,20 +195,14 @@ Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR } Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& index) { - if (!index.IsImmediate() || index.U32() != 0) { - throw NotImplementedException("Indirect image indexing"); - } + UNIMPLEMENTED_IF_MSG(!index.IsImmediate() || index.U32() != 0, "Indirect image indexing"); if (info.type == TextureType::Buffer) { const TextureBufferDefinition& def{ctx.texture_buffers.at(info.descriptor_index)}; - if (def.count > 1) { - throw NotImplementedException("Indirect texture sample"); - } - return ctx.OpLoad(ctx.image_buffer_type, def.id); + UNIMPLEMENTED_IF(def.count > 1); + return ctx.OpLoad(ctx.image_buffer_types[info.descriptor_index], def.id); } else { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; - if (def.count > 1) { - throw NotImplementedException("Indirect texture sample"); - } + UNIMPLEMENTED_IF(def.count > 1); return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); } } @@ -533,13 +525,10 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, if (ctx.profile.need_gather_subpixel_offset) { coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords); } - return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst, - ctx.F32[4], Texture(ctx, info, index), coords, dref, operands.MaskOptional(), - operands.Span()); + return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst, ctx.F32[4], Texture(ctx, info, index), coords, dref, operands.MaskOptional(), operands.Span()); } -Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, - Id lod, Id ms) { +Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, Id lod, Id ms) { const auto info{inst->Flags()}; AddOffsetToCoordinates(ctx, info, coords, offset); if (info.type == TextureType::Buffer) { @@ -549,9 +538,14 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c // This image is multisampled, lod must be implicit lod = Id{}; } + const auto is_integer = info.type == TextureType::Buffer + ? ctx.texture_buffers.at(info.descriptor_index).is_integer + : ctx.textures.at(info.descriptor_index).is_integer; const ImageOperands operands(lod, ms); - return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], - TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); + auto const result = Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, + is_integer ? ctx.U32[4] : ctx.F32[4], TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); + // TODO: Is this even correct????? + return is_integer ? ctx.OpConvertUToF(ctx.F32[4], result) : result; } Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, @@ -593,14 +587,11 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I zero, zero); } -Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, - Id derivatives, const IR::Value& offset, Id lod_clamp) { +Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id derivatives, const IR::Value& offset, Id lod_clamp) { const auto info{inst->Flags()}; const auto operands = info.num_derivatives == 3 - ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, - ctx.Def(offset), {}, lod_clamp) - : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, - info.num_derivatives, offset, lod_clamp); + ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, ctx.Def(offset), {}, lod_clamp) + : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset, lod_clamp); return Emit(&EmitContext::OpImageSparseSampleExplicitLod, &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index c70f9ae934..7260af7df5 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -30,9 +30,9 @@ enum class Operation { Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { const spv::ImageFormat format{spv::ImageFormat::Unknown}; - const Id type{ctx.F32[1]}; - const bool depth{desc.is_depth}; - const bool ms{desc.is_multisample}; + const Id type = desc.is_integer ? ctx.U32[1] : ctx.F32[1]; + const bool depth = desc.is_depth; + const bool ms = desc.is_multisample; switch (desc.type) { case TextureType::Color1D: return ctx.TypeImage(type, spv::Dim::Dim1D, depth, false, false, 1, format); @@ -1304,22 +1304,23 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) { if (info.texture_buffer_descriptors.empty()) { return; } - const spv::ImageFormat format{spv::ImageFormat::Unknown}; - image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); - - const Id type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)}; + const spv::ImageFormat format = spv::ImageFormat::Unknown; texture_buffers.reserve(info.texture_buffer_descriptors.size()); - for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) { - if (desc.count != 1) { - throw NotImplementedException("Array of texture buffers"); - } - const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)}; + for (size_t i = 0; i < info.texture_buffer_descriptors.size(); ++i) { + auto const& desc = info.texture_buffer_descriptors[i]; + UNIMPLEMENTED_IF(desc.count != 1); + + image_buffer_types[i] = TypeImage(desc.is_integer ? U32[1] : F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); + const Id type = TypePointer(spv::StorageClass::UniformConstant, image_buffer_types[i]); + + const Id id = AddGlobalVariable(type, spv::StorageClass::UniformConstant); Decorate(id, spv::Decoration::Binding, binding); Decorate(id, spv::Decoration::DescriptorSet, 0U); Name(id, NameOf(stage, desc, "texbuf")); texture_buffers.push_back({ .id = id, .count = desc.count, + .is_integer = desc.is_integer }); if (profile.supported_spirv >= 0x00010400) { interfaces.push_back(id); @@ -1374,6 +1375,7 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in .image_type = image_type, .count = desc.count, .is_multisample = desc.is_multisample, + .is_integer = desc.is_integer }); if (profile.supported_spirv >= 0x00010400) { interfaces.push_back(id); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 80ac79f2d6..f422d20ec4 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -41,11 +41,13 @@ struct TextureDefinition { Id image_type; u32 count; bool is_multisample; + bool is_integer; }; struct TextureBufferDefinition { Id id; u32 count; + bool is_integer; }; struct ImageBufferDefinition { @@ -248,7 +250,8 @@ public: Id output_f32{}; Id output_u32{}; - Id image_buffer_type{}; + // Max TextureBuffers? + std::array image_buffer_types{}; Id image_u32{}; std::array cbufs{}; diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index 0288db0ae1..02e091b4a2 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -429,7 +429,7 @@ public: texture_descriptors{texture_descriptors_}, image_descriptors{image_descriptors_} {} u32 Add(const TextureBufferDescriptor& desc) { - return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { + const u32 index = Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { return desc.cbuf_index == existing.cbuf_index && desc.cbuf_offset == existing.cbuf_offset && desc.shift_left == existing.shift_left && @@ -439,6 +439,8 @@ public: desc.count == existing.count && desc.size_shift == existing.size_shift && desc.has_secondary == existing.has_secondary; }); + texture_buffer_descriptors[index].is_integer |= desc.is_integer; + return index; } u32 Add(const ImageBufferDescriptor& desc) { @@ -465,7 +467,8 @@ public: desc.secondary_shift_left == existing.secondary_shift_left && desc.count == existing.count && desc.size_shift == existing.size_shift; })}; - // TODO: Read this from TIC + texture_descriptors[index].is_integer |= desc.is_integer; + // TODO: Read this from TIC (the MSAA whatever) texture_descriptors[index].is_multisample |= desc.is_multisample; return index; } @@ -632,6 +635,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo break; } u32 index; + const bool is_integer = IsTexturePixelFormatIntegerCached(env, cbuf); switch (inst->GetOpcode()) { case IR::Opcode::ImageRead: case IR::Opcode::ImageAtomicIAdd32: @@ -649,9 +653,8 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo if (cbuf.has_secondary) { throw NotImplementedException("Unexpected separate sampler"); } - const bool is_written{inst->GetOpcode() != IR::Opcode::ImageRead}; - const bool is_read{inst->GetOpcode() != IR::Opcode::ImageWrite}; - const bool is_integer{IsTexturePixelFormatIntegerCached(env, cbuf)}; + const bool is_written = inst->GetOpcode() != IR::Opcode::ImageRead; + const bool is_read = inst->GetOpcode() != IR::Opcode::ImageWrite; if (flags.type == TextureType::Buffer) { index = descriptors.Add(ImageBufferDescriptor{ .format = flags.image_format, @@ -682,6 +685,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo if (flags.type == TextureType::Buffer) { index = descriptors.Add(TextureBufferDescriptor{ .has_secondary = cbuf.has_secondary, + .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, .shift_left = cbuf.shift_left, @@ -696,6 +700,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .type = flags.type, .is_depth = flags.is_depth != 0, .is_multisample = is_multisample, + .is_integer = is_integer, .has_secondary = cbuf.has_secondary, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index dfacc06802..685567bb47 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -178,6 +178,7 @@ struct StorageBufferDescriptor { struct TextureBufferDescriptor { bool has_secondary; + bool is_integer; u32 cbuf_index; u32 cbuf_offset; u32 shift_left; @@ -209,6 +210,7 @@ struct TextureDescriptor { TextureType type; bool is_depth; bool is_multisample; + bool is_integer; bool has_secondary; u32 cbuf_index; u32 cbuf_offset; diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 85cdb948f3..10914b3ed7 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -65,9 +65,7 @@ static Shader::TextureType ConvertTextureType(const Tegra::Texture::TICEntry& en } static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture::TICEntry& entry) { - return static_cast( - PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type, - entry.a_type, entry.srgb_conversion)); + return Shader::TexturePixelFormat(PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type, entry.a_type, entry.srgb_conversion)); } static std::string_view StageToPrefix(Shader::Stage stage) { @@ -388,8 +386,7 @@ Shader::TexturePixelFormat GraphicsEnvironment::ReadTexturePixelFormat(u32 handl } bool GraphicsEnvironment::IsTexturePixelFormatInteger(u32 handle) { - return VideoCore::Surface::IsPixelFormatInteger( - static_cast(ReadTexturePixelFormat(handle))); + return VideoCore::Surface::IsPixelFormatInteger(VideoCore::Surface::PixelFormat(ReadTexturePixelFormat(handle))); } u32 GraphicsEnvironment::ReadViewportTransformState() { @@ -443,8 +440,7 @@ Shader::TexturePixelFormat ComputeEnvironment::ReadTexturePixelFormat(u32 handle } bool ComputeEnvironment::IsTexturePixelFormatInteger(u32 handle) { - return VideoCore::Surface::IsPixelFormatInteger( - static_cast(ReadTexturePixelFormat(handle))); + return VideoCore::Surface::IsPixelFormatInteger(VideoCore::Surface::PixelFormat(ReadTexturePixelFormat(handle))); } u32 ComputeEnvironment::ReadViewportTransformState() { @@ -551,8 +547,7 @@ Shader::TexturePixelFormat FileEnvironment::ReadTexturePixelFormat(u32 handle) { } bool FileEnvironment::IsTexturePixelFormatInteger(u32 handle) { - return VideoCore::Surface::IsPixelFormatInteger( - static_cast(ReadTexturePixelFormat(handle))); + return VideoCore::Surface::IsPixelFormatInteger(VideoCore::Surface::PixelFormat(ReadTexturePixelFormat(handle))); } u32 FileEnvironment::ReadViewportTransformState() { diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 1998849e84..96f4b2f6ac 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -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 @@ -242,39 +242,39 @@ SurfaceType GetFormatType(PixelFormat pixel_format) { bool HasAlpha(PixelFormat pixel_format) { switch (pixel_format) { - case PixelFormat::A8B8G8R8_UNORM: - case PixelFormat::A8B8G8R8_SNORM: - case PixelFormat::A8B8G8R8_SINT: - case PixelFormat::A8B8G8R8_UINT: - case PixelFormat::A1R5G5B5_UNORM: - case PixelFormat::A2B10G10R10_UNORM: - case PixelFormat::A2B10G10R10_UINT: - case PixelFormat::A2R10G10B10_UNORM: - case PixelFormat::A1B5G5R5_UNORM: - case PixelFormat::A5B5G5R1_UNORM: - case PixelFormat::R16G16B16A16_FLOAT: - case PixelFormat::R16G16B16A16_UNORM: - case PixelFormat::R16G16B16A16_SNORM: - case PixelFormat::R16G16B16A16_SINT: - case PixelFormat::R16G16B16A16_UINT: - case PixelFormat::R32G32B32A32_UINT: - case PixelFormat::BC1_RGBA_UNORM: - case PixelFormat::B8G8R8A8_UNORM: - case PixelFormat::R32G32B32A32_FLOAT: - case PixelFormat::R32G32B32A32_SINT: - case PixelFormat::A8B8G8R8_SRGB: - case PixelFormat::B8G8R8A8_SRGB: - case PixelFormat::BC1_RGBA_SRGB: - case PixelFormat::A4B4G4R4_UNORM: - case PixelFormat::BC2_SRGB: - case PixelFormat::BC2_UNORM: - case PixelFormat::BC3_SRGB: - case PixelFormat::BC3_UNORM: - case PixelFormat::BC7_SRGB: - case PixelFormat::BC7_UNORM: - return true; - default: - return false; + case PixelFormat::A8B8G8R8_UNORM: + case PixelFormat::A8B8G8R8_SNORM: + case PixelFormat::A8B8G8R8_SINT: + case PixelFormat::A8B8G8R8_UINT: + case PixelFormat::A1R5G5B5_UNORM: + case PixelFormat::A2B10G10R10_UNORM: + case PixelFormat::A2B10G10R10_UINT: + case PixelFormat::A2R10G10B10_UNORM: + case PixelFormat::A1B5G5R5_UNORM: + case PixelFormat::A5B5G5R1_UNORM: + case PixelFormat::R16G16B16A16_FLOAT: + case PixelFormat::R16G16B16A16_UNORM: + case PixelFormat::R16G16B16A16_SNORM: + case PixelFormat::R16G16B16A16_SINT: + case PixelFormat::R16G16B16A16_UINT: + case PixelFormat::R32G32B32A32_UINT: + case PixelFormat::BC1_RGBA_UNORM: + case PixelFormat::B8G8R8A8_UNORM: + case PixelFormat::R32G32B32A32_FLOAT: + case PixelFormat::R32G32B32A32_SINT: + case PixelFormat::A8B8G8R8_SRGB: + case PixelFormat::B8G8R8A8_SRGB: + case PixelFormat::BC1_RGBA_SRGB: + case PixelFormat::A4B4G4R4_UNORM: + case PixelFormat::BC2_SRGB: + case PixelFormat::BC2_UNORM: + case PixelFormat::BC3_SRGB: + case PixelFormat::BC3_UNORM: + case PixelFormat::BC7_SRGB: + case PixelFormat::BC7_UNORM: + return true; + default: + return false; } } diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp index 8c774f512c..0870951315 100644 --- a/src/video_core/texture_cache/format_lookup_table.cpp +++ b/src/video_core/texture_cache/format_lookup_table.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,243 +14,124 @@ using Tegra::Texture::ComponentType; using Tegra::Texture::TextureFormat; using VideoCore::Surface::PixelFormat; -namespace { - -constexpr auto SNORM = ComponentType::SNORM; -constexpr auto UNORM = ComponentType::UNORM; -constexpr auto SINT = ComponentType::SINT; -constexpr auto UINT = ComponentType::UINT; -constexpr auto FLOAT = ComponentType::FLOAT; constexpr bool LINEAR = false; constexpr bool SRGB = true; -constexpr u32 Hash(TextureFormat format, ComponentType red_component, ComponentType green_component, - ComponentType blue_component, ComponentType alpha_component, bool is_srgb) { - u32 hash = is_srgb ? 1 : 0; - hash |= static_cast(red_component) << 1; - hash |= static_cast(green_component) << 4; - hash |= static_cast(blue_component) << 7; - hash |= static_cast(alpha_component) << 10; - hash |= static_cast(format) << 13; - return hash; -} +// (TF2PF_ELEM[A-Z_0-9(]+, )([A-Z]+)(, LINEAR|. SRGB) +// $1$2, $2, $2, $2$3 +#define TF2PF_LIST \ + TF2PF_ELEM(A8B8G8R8, UNORM, UNORM, UNORM, UNORM, LINEAR, A8B8G8R8_UNORM) \ + TF2PF_ELEM(A8B8G8R8, UNORM, UNORM, UNORM, UNORM, SRGB, A8B8G8R8_SRGB) \ + TF2PF_ELEM(A8B8G8R8, SNORM, SNORM, SNORM, SNORM, LINEAR, A8B8G8R8_SNORM) \ + TF2PF_ELEM(A8B8G8R8, UINT, UINT, UINT, UINT, LINEAR, A8B8G8R8_UINT) \ + TF2PF_ELEM(A8B8G8R8, SINT, SINT, SINT, SINT, LINEAR, A8B8G8R8_SINT) \ + TF2PF_ELEM(B5G6R5, UNORM, UNORM, UNORM, UNORM, LINEAR, B5G6R5_UNORM) \ + TF2PF_ELEM(A2B10G10R10, UNORM, UNORM, UNORM, UNORM, LINEAR, A2B10G10R10_UNORM) \ + TF2PF_ELEM(A2B10G10R10, UINT, UINT, UINT, UINT, LINEAR, A2B10G10R10_UINT) \ + TF2PF_ELEM(A1B5G5R5, UNORM, UNORM, UNORM, UNORM, LINEAR, A1B5G5R5_UNORM) \ + TF2PF_ELEM(A4B4G4R4, UNORM, UNORM, UNORM, UNORM, LINEAR, A4B4G4R4_UNORM) \ + TF2PF_ELEM(G4R4, UNORM, UNORM, UNORM, UNORM, LINEAR, G4R4_UNORM) \ + TF2PF_ELEM(A5B5G5R1, UNORM, UNORM, UNORM, UNORM, LINEAR, A5B5G5R1_UNORM) \ + TF2PF_ELEM(R8, UNORM, UNORM, UNORM, UNORM, LINEAR, R8_UNORM) \ + TF2PF_ELEM(R8, SNORM, SNORM, SNORM, SNORM, LINEAR, R8_SNORM) \ + TF2PF_ELEM(R8, UINT, UINT, UINT, UINT, LINEAR, R8_UINT) \ + TF2PF_ELEM(R8, SINT, SINT, SINT, SINT, LINEAR, R8_SINT) \ + TF2PF_ELEM(G8R8, UNORM, UNORM, UNORM, UNORM, LINEAR, R8G8_UNORM) \ + TF2PF_ELEM(G8R8, SNORM, SNORM, SNORM, SNORM, LINEAR, R8G8_SNORM) \ + TF2PF_ELEM(G8R8, UINT, UINT, UINT, UINT, LINEAR, R8G8_UINT) \ + TF2PF_ELEM(G8R8, SINT, SINT, SINT, SINT, LINEAR, R8G8_SINT) \ + TF2PF_ELEM(R16G16B16A16, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, R16G16B16A16_FLOAT) \ + TF2PF_ELEM(R16G16B16A16, UNORM, UNORM, UNORM, UNORM, LINEAR, R16G16B16A16_UNORM) \ + TF2PF_ELEM(R16G16B16A16, SNORM, SNORM, SNORM, SNORM, LINEAR, R16G16B16A16_SNORM) \ + TF2PF_ELEM(R16G16B16A16, UINT, UINT, UINT, UINT, LINEAR, R16G16B16A16_UINT) \ + TF2PF_ELEM(R16G16B16A16, SINT, SINT, SINT, SINT, LINEAR, R16G16B16A16_SINT) \ + TF2PF_ELEM(R16G16, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, R16G16_FLOAT) \ + TF2PF_ELEM(R16G16, UNORM, UNORM, UNORM, UNORM, LINEAR, R16G16_UNORM) \ + TF2PF_ELEM(R16G16, SNORM, SNORM, SNORM, SNORM, LINEAR, R16G16_SNORM) \ + TF2PF_ELEM(R16G16, UINT, UINT, UINT, UINT, LINEAR, R16G16_UINT) \ + TF2PF_ELEM(R16G16, SINT, SINT, SINT, SINT, LINEAR, R16G16_SINT) \ + TF2PF_ELEM(R16, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, R16_FLOAT) \ + TF2PF_ELEM(R16, UNORM, UNORM, UNORM, UNORM, LINEAR, R16_UNORM) \ + TF2PF_ELEM(R16, SNORM, SNORM, SNORM, SNORM, LINEAR, R16_SNORM) \ + TF2PF_ELEM(R16, UINT, UINT, UINT, UINT, LINEAR, R16_UINT) \ + TF2PF_ELEM(R16, SINT, SINT, SINT, SINT, LINEAR, R16_SINT) \ + TF2PF_ELEM(B10G11R11, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, B10G11R11_FLOAT) \ + TF2PF_ELEM(R32G32B32A32, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, R32G32B32A32_FLOAT) \ + TF2PF_ELEM(R32G32B32A32, UINT, UINT, UINT, UINT, LINEAR, R32G32B32A32_UINT) \ + TF2PF_ELEM(R32G32B32A32, SINT, SINT, SINT, SINT, LINEAR, R32G32B32A32_SINT) \ + TF2PF_ELEM(R32G32B32, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, R32G32B32_FLOAT) \ + TF2PF_ELEM(R32G32, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, R32G32_FLOAT) \ + TF2PF_ELEM(R32G32, UINT, UINT, UINT, UINT, LINEAR, R32G32_UINT) \ + TF2PF_ELEM(R32G32, SINT, SINT, SINT, SINT, LINEAR, R32G32_SINT) \ + TF2PF_ELEM(R32, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, R32_FLOAT) \ + TF2PF_ELEM(R32, UINT, UINT, UINT, UINT, LINEAR, R32_UINT) \ + TF2PF_ELEM(R32, SINT, SINT, SINT, SINT, LINEAR, R32_SINT) \ + TF2PF_ELEM(E5B9G9R9, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, E5B9G9R9_FLOAT) \ + TF2PF_ELEM(Z32, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, D32_FLOAT) \ + TF2PF_ELEM(Z32, FLOAT, UINT, UINT, UINT, LINEAR, D32_FLOAT) \ + TF2PF_ELEM(Z16, UNORM, UNORM, UNORM, UNORM, LINEAR, D16_UNORM) \ + TF2PF_ELEM(Z16, UNORM, UINT, UINT, UINT, LINEAR, D16_UNORM) \ + TF2PF_ELEM(X8Z24, UNORM, UNORM, UNORM, UNORM, LINEAR, X8_D24_UNORM) \ + TF2PF_ELEM(X8Z24, UNORM, UINT, UINT, UINT, LINEAR, X8_D24_UNORM) \ + TF2PF_ELEM(Z24S8, UINT, UNORM, UNORM, UNORM, LINEAR, S8_UINT_D24_UNORM) \ + TF2PF_ELEM(Z24S8, UINT, UNORM, UINT, UINT, LINEAR, S8_UINT_D24_UNORM) \ + TF2PF_ELEM(G24R8, UINT, UNORM, UNORM, UNORM, LINEAR, S8_UINT_D24_UNORM) \ + TF2PF_ELEM(S8Z24, UNORM, UINT, UINT, UINT, LINEAR, D24_UNORM_S8_UINT) \ + TF2PF_ELEM(Z32_X24S8, FLOAT, UINT, UNORM, UNORM, LINEAR, D32_FLOAT_S8_UINT) \ + TF2PF_ELEM(R32B24G8, FLOAT, UINT, UNORM, UNORM, LINEAR, D32_FLOAT_S8_UINT) \ + TF2PF_ELEM(DXT1, UNORM, UNORM, UNORM, UNORM, LINEAR, BC1_RGBA_UNORM) \ + TF2PF_ELEM(DXT1, UNORM, UNORM, UNORM, UNORM, SRGB, BC1_RGBA_SRGB) \ + TF2PF_ELEM(DXT23, UNORM, UNORM, UNORM, UNORM, LINEAR, BC2_UNORM) \ + TF2PF_ELEM(DXT23, UNORM, UNORM, UNORM, UNORM, SRGB, BC2_SRGB) \ + TF2PF_ELEM(DXT45, UNORM, UNORM, UNORM, UNORM, LINEAR, BC3_UNORM) \ + TF2PF_ELEM(DXT45, UNORM, UNORM, UNORM, UNORM, SRGB, BC3_SRGB) \ + TF2PF_ELEM(DXN1, UNORM, UNORM, UNORM, UNORM, LINEAR, BC4_UNORM) \ + TF2PF_ELEM(DXN1, SNORM, SNORM, SNORM, SNORM, LINEAR, BC4_SNORM) \ + TF2PF_ELEM(DXN2, UNORM, UNORM, UNORM, UNORM, LINEAR, BC5_UNORM) \ + TF2PF_ELEM(DXN2, SNORM, SNORM, SNORM, SNORM, LINEAR, BC5_SNORM) \ + TF2PF_ELEM(BC7U, UNORM, UNORM, UNORM, UNORM, LINEAR, BC7_UNORM) \ + TF2PF_ELEM(BC7U, UNORM, UNORM, UNORM, UNORM, SRGB, BC7_SRGB) \ + TF2PF_ELEM(BC6H_S16, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, BC6H_SFLOAT) \ + TF2PF_ELEM(BC6H_U16, FLOAT, FLOAT, FLOAT, FLOAT, LINEAR, BC6H_UFLOAT) \ + TF2PF_ELEM(ASTC_2D_4X4, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_4X4_UNORM) \ + TF2PF_ELEM(ASTC_2D_4X4, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_4X4_SRGB) \ + TF2PF_ELEM(ASTC_2D_5X4, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_5X4_UNORM) \ + TF2PF_ELEM(ASTC_2D_5X4, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_5X4_SRGB) \ + TF2PF_ELEM(ASTC_2D_5X5, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_5X5_UNORM) \ + TF2PF_ELEM(ASTC_2D_5X5, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_5X5_SRGB) \ + TF2PF_ELEM(ASTC_2D_8X8, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_8X8_UNORM) \ + TF2PF_ELEM(ASTC_2D_8X8, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_8X8_SRGB) \ + TF2PF_ELEM(ASTC_2D_8X5, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_8X5_UNORM) \ + TF2PF_ELEM(ASTC_2D_8X5, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_8X5_SRGB) \ + TF2PF_ELEM(ASTC_2D_10X8, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_10X8_UNORM) \ + TF2PF_ELEM(ASTC_2D_10X8, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_10X8_SRGB) \ + TF2PF_ELEM(ASTC_2D_6X6, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_6X6_UNORM) \ + TF2PF_ELEM(ASTC_2D_6X6, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_6X6_SRGB) \ + TF2PF_ELEM(ASTC_2D_10X6, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_10X6_UNORM) \ + TF2PF_ELEM(ASTC_2D_10X6, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_10X6_SRGB) \ + TF2PF_ELEM(ASTC_2D_10X5, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_10X5_UNORM) \ + TF2PF_ELEM(ASTC_2D_10X5, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_10X5_SRGB) \ + TF2PF_ELEM(ASTC_2D_10X10, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_10X10_UNORM) \ + TF2PF_ELEM(ASTC_2D_10X10, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_10X10_SRGB) \ + TF2PF_ELEM(ASTC_2D_12X10, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_12X10_UNORM) \ + TF2PF_ELEM(ASTC_2D_12X10, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_12X10_SRGB) \ + TF2PF_ELEM(ASTC_2D_12X12, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_12X12_UNORM) \ + TF2PF_ELEM(ASTC_2D_12X12, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_12X12_SRGB) \ + TF2PF_ELEM(ASTC_2D_8X6, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_8X6_UNORM) \ + TF2PF_ELEM(ASTC_2D_8X6, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_8X6_SRGB) \ + TF2PF_ELEM(ASTC_2D_6X5, UNORM, UNORM, UNORM, UNORM, LINEAR, ASTC_2D_6X5_UNORM) \ + TF2PF_ELEM(ASTC_2D_6X5, UNORM, UNORM, UNORM, UNORM, SRGB, ASTC_2D_6X5_SRGB) \ -constexpr u32 Hash(TextureFormat format, ComponentType component, bool is_srgb = LINEAR) { - return Hash(format, component, component, component, component, is_srgb); -} - -} // Anonymous namespace - -PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red, ComponentType green, - ComponentType blue, ComponentType alpha, - bool is_srgb) noexcept { - switch (Hash(format, red, green, blue, alpha, is_srgb)) { - case Hash(TextureFormat::A8B8G8R8, UNORM): - return PixelFormat::A8B8G8R8_UNORM; - case Hash(TextureFormat::A8B8G8R8, SNORM): - return PixelFormat::A8B8G8R8_SNORM; - case Hash(TextureFormat::A8B8G8R8, UINT): - return PixelFormat::A8B8G8R8_UINT; - case Hash(TextureFormat::A8B8G8R8, SINT): - return PixelFormat::A8B8G8R8_SINT; - case Hash(TextureFormat::A8B8G8R8, UNORM, SRGB): - return PixelFormat::A8B8G8R8_SRGB; - case Hash(TextureFormat::B5G6R5, UNORM): - return PixelFormat::B5G6R5_UNORM; - case Hash(TextureFormat::A2B10G10R10, UNORM): - return PixelFormat::A2B10G10R10_UNORM; - case Hash(TextureFormat::A2B10G10R10, UINT): - return PixelFormat::A2B10G10R10_UINT; - case Hash(TextureFormat::A1B5G5R5, UNORM): - return PixelFormat::A1B5G5R5_UNORM; - case Hash(TextureFormat::A4B4G4R4, UNORM): - return PixelFormat::A4B4G4R4_UNORM; - case Hash(TextureFormat::G4R4, UNORM): - return PixelFormat::G4R4_UNORM; - case Hash(TextureFormat::A5B5G5R1, UNORM): - return PixelFormat::A5B5G5R1_UNORM; - case Hash(TextureFormat::R8, UNORM): - return PixelFormat::R8_UNORM; - case Hash(TextureFormat::R8, SNORM): - return PixelFormat::R8_SNORM; - case Hash(TextureFormat::R8, UINT): - return PixelFormat::R8_UINT; - case Hash(TextureFormat::R8, SINT): - return PixelFormat::R8_SINT; - case Hash(TextureFormat::G8R8, UNORM): - return PixelFormat::R8G8_UNORM; - case Hash(TextureFormat::G8R8, SNORM): - return PixelFormat::R8G8_SNORM; - case Hash(TextureFormat::G8R8, UINT): - return PixelFormat::R8G8_UINT; - case Hash(TextureFormat::G8R8, SINT): - return PixelFormat::R8G8_SINT; - case Hash(TextureFormat::R16G16B16A16, FLOAT): - return PixelFormat::R16G16B16A16_FLOAT; - case Hash(TextureFormat::R16G16B16A16, UNORM): - return PixelFormat::R16G16B16A16_UNORM; - case Hash(TextureFormat::R16G16B16A16, SNORM): - return PixelFormat::R16G16B16A16_SNORM; - case Hash(TextureFormat::R16G16B16A16, UINT): - return PixelFormat::R16G16B16A16_UINT; - case Hash(TextureFormat::R16G16B16A16, SINT): - return PixelFormat::R16G16B16A16_SINT; - case Hash(TextureFormat::R16G16, FLOAT): - return PixelFormat::R16G16_FLOAT; - case Hash(TextureFormat::R16G16, UNORM): - return PixelFormat::R16G16_UNORM; - case Hash(TextureFormat::R16G16, SNORM): - return PixelFormat::R16G16_SNORM; - case Hash(TextureFormat::R16G16, UINT): - return PixelFormat::R16G16_UINT; - case Hash(TextureFormat::R16G16, SINT): - return PixelFormat::R16G16_SINT; - case Hash(TextureFormat::R16, FLOAT): - return PixelFormat::R16_FLOAT; - case Hash(TextureFormat::R16, UNORM): - return PixelFormat::R16_UNORM; - case Hash(TextureFormat::R16, SNORM): - return PixelFormat::R16_SNORM; - case Hash(TextureFormat::R16, UINT): - return PixelFormat::R16_UINT; - case Hash(TextureFormat::R16, SINT): - return PixelFormat::R16_SINT; - case Hash(TextureFormat::B10G11R11, FLOAT): - return PixelFormat::B10G11R11_FLOAT; - case Hash(TextureFormat::R32G32B32A32, FLOAT): - return PixelFormat::R32G32B32A32_FLOAT; - case Hash(TextureFormat::R32G32B32A32, UINT): - return PixelFormat::R32G32B32A32_UINT; - case Hash(TextureFormat::R32G32B32A32, SINT): - return PixelFormat::R32G32B32A32_SINT; - case Hash(TextureFormat::R32G32B32, FLOAT): - return PixelFormat::R32G32B32_FLOAT; - case Hash(TextureFormat::R32G32, FLOAT): - return PixelFormat::R32G32_FLOAT; - case Hash(TextureFormat::R32G32, UINT): - return PixelFormat::R32G32_UINT; - case Hash(TextureFormat::R32G32, SINT): - return PixelFormat::R32G32_SINT; - case Hash(TextureFormat::R32, FLOAT): - return PixelFormat::R32_FLOAT; - case Hash(TextureFormat::R32, UINT): - return PixelFormat::R32_UINT; - case Hash(TextureFormat::R32, SINT): - return PixelFormat::R32_SINT; - case Hash(TextureFormat::E5B9G9R9, FLOAT): - return PixelFormat::E5B9G9R9_FLOAT; - case Hash(TextureFormat::Z32, FLOAT): - return PixelFormat::D32_FLOAT; - case Hash(TextureFormat::Z32, FLOAT, UINT, UINT, UINT, LINEAR): - return PixelFormat::D32_FLOAT; - case Hash(TextureFormat::Z16, UNORM): - return PixelFormat::D16_UNORM; - case Hash(TextureFormat::Z16, UNORM, UINT, UINT, UINT, LINEAR): - return PixelFormat::D16_UNORM; - case Hash(TextureFormat::X8Z24, UNORM): - return PixelFormat::X8_D24_UNORM; - case Hash(TextureFormat::X8Z24, UNORM, UINT, UINT, UINT, LINEAR): - return PixelFormat::X8_D24_UNORM; - case Hash(TextureFormat::Z24S8, UINT, UNORM, UNORM, UNORM, LINEAR): - return PixelFormat::S8_UINT_D24_UNORM; - case Hash(TextureFormat::Z24S8, UINT, UNORM, UINT, UINT, LINEAR): - return PixelFormat::S8_UINT_D24_UNORM; - case Hash(TextureFormat::G24R8, UINT, UNORM, UNORM, UNORM, LINEAR): - return PixelFormat::S8_UINT_D24_UNORM; - case Hash(TextureFormat::S8Z24, UNORM, UINT, UINT, UINT, LINEAR): - return PixelFormat::D24_UNORM_S8_UINT; - case Hash(TextureFormat::Z32_X24S8, FLOAT, UINT, UNORM, UNORM, LINEAR): - return PixelFormat::D32_FLOAT_S8_UINT; - case Hash(TextureFormat::R32B24G8, FLOAT, UINT, UNORM, UNORM, LINEAR): - return PixelFormat::D32_FLOAT_S8_UINT; - case Hash(TextureFormat::DXT1, UNORM, LINEAR): - return PixelFormat::BC1_RGBA_UNORM; - case Hash(TextureFormat::DXT1, UNORM, SRGB): - return PixelFormat::BC1_RGBA_SRGB; - case Hash(TextureFormat::DXT23, UNORM, LINEAR): - return PixelFormat::BC2_UNORM; - case Hash(TextureFormat::DXT23, UNORM, SRGB): - return PixelFormat::BC2_SRGB; - case Hash(TextureFormat::DXT45, UNORM, LINEAR): - return PixelFormat::BC3_UNORM; - case Hash(TextureFormat::DXT45, UNORM, SRGB): - return PixelFormat::BC3_SRGB; - case Hash(TextureFormat::DXN1, UNORM): - return PixelFormat::BC4_UNORM; - case Hash(TextureFormat::DXN1, SNORM): - return PixelFormat::BC4_SNORM; - case Hash(TextureFormat::DXN2, UNORM): - return PixelFormat::BC5_UNORM; - case Hash(TextureFormat::DXN2, SNORM): - return PixelFormat::BC5_SNORM; - case Hash(TextureFormat::BC7U, UNORM, LINEAR): - return PixelFormat::BC7_UNORM; - case Hash(TextureFormat::BC7U, UNORM, SRGB): - return PixelFormat::BC7_SRGB; - case Hash(TextureFormat::BC6H_S16, FLOAT): - return PixelFormat::BC6H_SFLOAT; - case Hash(TextureFormat::BC6H_U16, FLOAT): - return PixelFormat::BC6H_UFLOAT; - case Hash(TextureFormat::ASTC_2D_4X4, UNORM, LINEAR): - return PixelFormat::ASTC_2D_4X4_UNORM; - case Hash(TextureFormat::ASTC_2D_4X4, UNORM, SRGB): - return PixelFormat::ASTC_2D_4X4_SRGB; - case Hash(TextureFormat::ASTC_2D_5X4, UNORM, LINEAR): - return PixelFormat::ASTC_2D_5X4_UNORM; - case Hash(TextureFormat::ASTC_2D_5X4, UNORM, SRGB): - return PixelFormat::ASTC_2D_5X4_SRGB; - case Hash(TextureFormat::ASTC_2D_5X5, UNORM, LINEAR): - return PixelFormat::ASTC_2D_5X5_UNORM; - case Hash(TextureFormat::ASTC_2D_5X5, UNORM, SRGB): - return PixelFormat::ASTC_2D_5X5_SRGB; - case Hash(TextureFormat::ASTC_2D_8X8, UNORM, LINEAR): - return PixelFormat::ASTC_2D_8X8_UNORM; - case Hash(TextureFormat::ASTC_2D_8X8, UNORM, SRGB): - return PixelFormat::ASTC_2D_8X8_SRGB; - case Hash(TextureFormat::ASTC_2D_8X5, UNORM, LINEAR): - return PixelFormat::ASTC_2D_8X5_UNORM; - case Hash(TextureFormat::ASTC_2D_8X5, UNORM, SRGB): - return PixelFormat::ASTC_2D_8X5_SRGB; - case Hash(TextureFormat::ASTC_2D_10X8, UNORM, LINEAR): - return PixelFormat::ASTC_2D_10X8_UNORM; - case Hash(TextureFormat::ASTC_2D_10X8, UNORM, SRGB): - return PixelFormat::ASTC_2D_10X8_SRGB; - case Hash(TextureFormat::ASTC_2D_6X6, UNORM, LINEAR): - return PixelFormat::ASTC_2D_6X6_UNORM; - case Hash(TextureFormat::ASTC_2D_6X6, UNORM, SRGB): - return PixelFormat::ASTC_2D_6X6_SRGB; - case Hash(TextureFormat::ASTC_2D_10X6, UNORM, LINEAR): - return PixelFormat::ASTC_2D_10X6_UNORM; - case Hash(TextureFormat::ASTC_2D_10X6, UNORM, SRGB): - return PixelFormat::ASTC_2D_10X6_SRGB; - case Hash(TextureFormat::ASTC_2D_10X5, UNORM, LINEAR): - return PixelFormat::ASTC_2D_10X5_UNORM; - case Hash(TextureFormat::ASTC_2D_10X5, UNORM, SRGB): - return PixelFormat::ASTC_2D_10X5_SRGB; - case Hash(TextureFormat::ASTC_2D_10X10, UNORM, LINEAR): - return PixelFormat::ASTC_2D_10X10_UNORM; - case Hash(TextureFormat::ASTC_2D_10X10, UNORM, SRGB): - return PixelFormat::ASTC_2D_10X10_SRGB; - case Hash(TextureFormat::ASTC_2D_12X10, UNORM, LINEAR): - return PixelFormat::ASTC_2D_12X10_UNORM; - case Hash(TextureFormat::ASTC_2D_12X10, UNORM, SRGB): - return PixelFormat::ASTC_2D_12X10_SRGB; - case Hash(TextureFormat::ASTC_2D_12X12, UNORM, LINEAR): - return PixelFormat::ASTC_2D_12X12_UNORM; - case Hash(TextureFormat::ASTC_2D_12X12, UNORM, SRGB): - return PixelFormat::ASTC_2D_12X12_SRGB; - case Hash(TextureFormat::ASTC_2D_8X6, UNORM, LINEAR): - return PixelFormat::ASTC_2D_8X6_UNORM; - case Hash(TextureFormat::ASTC_2D_8X6, UNORM, SRGB): - return PixelFormat::ASTC_2D_8X6_SRGB; - case Hash(TextureFormat::ASTC_2D_6X5, UNORM, LINEAR): - return PixelFormat::ASTC_2D_6X5_UNORM; - case Hash(TextureFormat::ASTC_2D_6X5, UNORM, SRGB): - return PixelFormat::ASTC_2D_6X5_SRGB; - } - UNIMPLEMENTED_MSG("texture format={} srgb={} components={{{} {} {} {}}}", - static_cast(format), is_srgb, static_cast(red), - static_cast(green), static_cast(blue), static_cast(alpha)); +PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red, ComponentType green, ComponentType blue, ComponentType alpha, bool is_srgb) noexcept { + if (false) { /* no op */ } +#define TF2PF_ELEM(FMT, CR, CG, CB, CA, SRGB, RES) \ + else if (format == TextureFormat::FMT \ + && red == ComponentType::CR && green == ComponentType::CG \ + && blue == ComponentType::CB && alpha == ComponentType::CA \ + && is_srgb == SRGB) return PixelFormat::RES; + TF2PF_LIST +#undef TF2PF_ELEM + UNIMPLEMENTED_MSG("texture format={} srgb={} components={{{} {} {} {}}}", int(format), is_srgb, int(red), int(green), int(blue), int(alpha)); return PixelFormat::A8B8G8R8_UNORM; }