diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index a7bb39d39478..5a5118932bcc 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -137,7 +137,7 @@ void DolphinAnalytics::ReportGameStart() } // Keep in sync with enum class GameQuirk definition. -constexpr std::array GAME_QUIRKS_NAMES{ +constexpr std::array GAME_QUIRKS_NAMES{ "directly-reads-wiimote-input", "uses-DVDLowStopLaser", "uses-DVDLowOffset", @@ -166,6 +166,10 @@ constexpr std::array GAME_QUIRKS_NAMES{ "mismatched-gpu-tex-coords-between-cp-and-xf", "mismatched-gpu-matrix-indices-between-cp-and-xf", "reads-bounding-box", + "invalid-position-component-format", + "invalid-normal-component-format", + "invalid-texture-coordinate-component-format", + "invalid-color-component-format", }; static_assert(GAME_QUIRKS_NAMES.size() == static_cast(GameQuirk::COUNT), "Game quirks names and enum definition are out of sync."); diff --git a/Source/Core/Core/DolphinAnalytics.h b/Source/Core/Core/DolphinAnalytics.h index 76e69f49c238..7e701c9a3618 100644 --- a/Source/Core/Core/DolphinAnalytics.h +++ b/Source/Core/Core/DolphinAnalytics.h @@ -94,6 +94,15 @@ enum class GameQuirk // only a few read them (from PE_BBOX_LEFT etc.) READS_BOUNDING_BOX, + // A few games use invalid vertex component formats, but the two known cases (Fifa Street and + // Def Jam: Fight for New York, see https://bugs.dolphin-emu.org/issues/12719) only use invalid + // normal formats and lighting is disabled in those cases, so it doesn't end up mattering. + // It's possible other games use invalid formats, possibly on other vertex components. + INVALID_POSITION_COMPONENT_FORMAT, + INVALID_NORMAL_COMPONENT_FORMAT, + INVALID_TEXTURE_COORDINATE_COMPONENT_FORMAT, + INVALID_COLOR_COMPONENT_FORMAT, + COUNT, }; diff --git a/Source/Core/VideoBackends/D3D/D3DNativeVertexFormat.cpp b/Source/Core/VideoBackends/D3D/D3DNativeVertexFormat.cpp index 54c1ae8220f3..0f81db9aaab0 100644 --- a/Source/Core/VideoBackends/D3D/D3DNativeVertexFormat.cpp +++ b/Source/Core/VideoBackends/D3D/D3DNativeVertexFormat.cpp @@ -25,7 +25,7 @@ Gfx::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) { - using FormatMap = Common::EnumMap; + using FormatMap = Common::EnumMap; static constexpr auto f = [](FormatMap a) { return a; }; // Deduction helper static constexpr std::array d3d_float_format_lookup = { @@ -35,6 +35,9 @@ DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, }), f({ DXGI_FORMAT_R8G8_UNORM, @@ -42,6 +45,9 @@ DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, }), f({ DXGI_FORMAT_UNKNOWN, @@ -49,6 +55,9 @@ DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32_FLOAT, }), f({ DXGI_FORMAT_R8G8B8A8_UNORM, @@ -56,6 +65,9 @@ DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, }), }; @@ -66,6 +78,9 @@ DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, }), f({ DXGI_FORMAT_R8G8_UINT, @@ -73,6 +88,9 @@ DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, }), f({ DXGI_FORMAT_UNKNOWN, @@ -80,6 +98,9 @@ DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, }), f({ DXGI_FORMAT_R8G8B8A8_UINT, @@ -87,6 +108,9 @@ DXGI_FORMAT VarToD3D(ComponentFormat t, int size, bool integer) DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, }), }; diff --git a/Source/Core/VideoBackends/D3D12/DX12VertexFormat.cpp b/Source/Core/VideoBackends/D3D12/DX12VertexFormat.cpp index 6ba3a8800d22..69a1d6a2902d 100644 --- a/Source/Core/VideoBackends/D3D12/DX12VertexFormat.cpp +++ b/Source/Core/VideoBackends/D3D12/DX12VertexFormat.cpp @@ -17,31 +17,45 @@ static DXGI_FORMAT VarToDXGIFormat(ComponentFormat t, u32 components, bool integ static constexpr auto f = [](ComponentArray a) { return a; }; // Deduction helper // NOTE: 3-component formats are not valid. - static constexpr Common::EnumMap float_type_lookup = { - f({DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM}), // UByte - f({DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, - DXGI_FORMAT_R8G8B8A8_SNORM}), // Byte - f({DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, - DXGI_FORMAT_R16G16B16A16_UNORM}), // UShort - f({DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16B16A16_SNORM, - DXGI_FORMAT_R16G16B16A16_SNORM}), // Short - f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT}), // Float - }; - - static constexpr Common::EnumMap integer_type_lookup = { - f({DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, - DXGI_FORMAT_R8G8B8A8_UINT}), // UByte - f({DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, - DXGI_FORMAT_R8G8B8A8_SINT}), // Byte - f({DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, - DXGI_FORMAT_R16G16B16A16_UINT}), // UShort - f({DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, - DXGI_FORMAT_R16G16B16A16_SINT}), // Short - f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT}), // Float - }; + static constexpr Common::EnumMap + float_type_lookup = { + f({DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM}), // UByte + f({DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM}), // Byte + f({DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM}), // UShort + f({DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM}), // Short + f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT}), // Float + f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT}), // Invalid + f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT}), // Invalid + f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT}), // Invalid + }; + + static constexpr Common::EnumMap + integer_type_lookup = { + f({DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT}), // UByte + f({DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT}), // Byte + f({DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT}), // UShort + f({DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT}), // Short + f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT}), // Float + f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT}), // Invalid + f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT}), // Invalid + f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT}), // Invalid + }; ASSERT(components > 0 && components <= 4); return integer ? integer_type_lookup[t][components - 1] : float_type_lookup[t][components - 1]; diff --git a/Source/Core/VideoBackends/Metal/MTLVertexFormat.mm b/Source/Core/VideoBackends/Metal/MTLVertexFormat.mm index 5fffad8b5751..a73247b4f73b 100644 --- a/Source/Core/VideoBackends/Metal/MTLVertexFormat.mm +++ b/Source/Core/VideoBackends/Metal/MTLVertexFormat.mm @@ -49,6 +49,9 @@ static MTLVertexFormat ConvertFormat(ComponentFormat format, int count, bool int default: return MTLVertexFormatInvalid; } case ComponentFormat::Float: + case ComponentFormat::InvalidFloat5: + case ComponentFormat::InvalidFloat6: + case ComponentFormat::InvalidFloat7: switch (count) { case 1: return MTLVertexFormatFloat; @@ -100,6 +103,9 @@ static MTLVertexFormat ConvertFormat(ComponentFormat format, int count, bool int default: return MTLVertexFormatInvalid; } case ComponentFormat::Float: + case ComponentFormat::InvalidFloat5: + case ComponentFormat::InvalidFloat6: + case ComponentFormat::InvalidFloat7: switch (count) { case 1: return MTLVertexFormatFloat; diff --git a/Source/Core/VideoBackends/OGL/OGLNativeVertexFormat.cpp b/Source/Core/VideoBackends/OGL/OGLNativeVertexFormat.cpp index f1213fcde53e..7e478843b662 100644 --- a/Source/Core/VideoBackends/OGL/OGLNativeVertexFormat.cpp +++ b/Source/Core/VideoBackends/OGL/OGLNativeVertexFormat.cpp @@ -26,8 +26,9 @@ OGLGfx::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) static inline GLuint VarToGL(ComponentFormat t) { - static constexpr Common::EnumMap lookup = { - GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_FLOAT, + static constexpr Common::EnumMap lookup = { + GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, + GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, }; return lookup[t]; } diff --git a/Source/Core/VideoBackends/Software/SWVertexLoader.cpp b/Source/Core/VideoBackends/Software/SWVertexLoader.cpp index 903b430aff2b..cfb05d096b77 100644 --- a/Source/Core/VideoBackends/Software/SWVertexLoader.cpp +++ b/Source/Core/VideoBackends/Software/SWVertexLoader.cpp @@ -149,11 +149,14 @@ static void ReadVertexAttribute(T* dst, DataReader src, const AttributeFormat& f dst[i_dst] = ReadNormalized(src.Read()); break; case ComponentFormat::Float: + case ComponentFormat::InvalidFloat5: + case ComponentFormat::InvalidFloat6: + case ComponentFormat::InvalidFloat7: dst[i_dst] = ReadNormalized(src.Read()); break; } - ASSERT_MSG(VIDEO, !format.integer || format.type != ComponentFormat::Float, + ASSERT_MSG(VIDEO, !format.integer || (format.type < ComponentFormat::Float), "only non-float values are allowed to be streamed as integer"); } for (; i < components; i++) diff --git a/Source/Core/VideoBackends/Vulkan/VKVertexFormat.cpp b/Source/Core/VideoBackends/Vulkan/VKVertexFormat.cpp index 65b63b32b98c..8fb49f0afdb3 100644 --- a/Source/Core/VideoBackends/Vulkan/VKVertexFormat.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKVertexFormat.cpp @@ -19,31 +19,45 @@ static VkFormat VarToVkFormat(ComponentFormat t, uint32_t components, bool integ using ComponentArray = std::array; static constexpr auto f = [](ComponentArray a) { return a; }; // Deduction helper - static constexpr Common::EnumMap float_type_lookup = { - f({VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8B8_UNORM, - VK_FORMAT_R8G8B8A8_UNORM}), // UByte - f({VK_FORMAT_R8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8B8_SNORM, - VK_FORMAT_R8G8B8A8_SNORM}), // Byte - f({VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16B16_UNORM, - VK_FORMAT_R16G16B16A16_UNORM}), // UShort - f({VK_FORMAT_R16_SNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16B16_SNORM, - VK_FORMAT_R16G16B16A16_SNORM}), // Short - f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, - VK_FORMAT_R32G32B32A32_SFLOAT}), // Float - }; - - static constexpr Common::EnumMap integer_type_lookup = { - f({VK_FORMAT_R8_UINT, VK_FORMAT_R8G8_UINT, VK_FORMAT_R8G8B8_UINT, - VK_FORMAT_R8G8B8A8_UINT}), // UByte - f({VK_FORMAT_R8_SINT, VK_FORMAT_R8G8_SINT, VK_FORMAT_R8G8B8_SINT, - VK_FORMAT_R8G8B8A8_SINT}), // Byte - f({VK_FORMAT_R16_UINT, VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16B16_UINT, - VK_FORMAT_R16G16B16A16_UINT}), // UShort - f({VK_FORMAT_R16_SINT, VK_FORMAT_R16G16_SINT, VK_FORMAT_R16G16B16_SINT, - VK_FORMAT_R16G16B16A16_SINT}), // Short - f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, - VK_FORMAT_R32G32B32A32_SFLOAT}), // Float - }; + static constexpr Common::EnumMap + float_type_lookup = { + f({VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8B8_UNORM, + VK_FORMAT_R8G8B8A8_UNORM}), // UByte + f({VK_FORMAT_R8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8B8_SNORM, + VK_FORMAT_R8G8B8A8_SNORM}), // Byte + f({VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16B16_UNORM, + VK_FORMAT_R16G16B16A16_UNORM}), // UShort + f({VK_FORMAT_R16_SNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16B16_SNORM, + VK_FORMAT_R16G16B16A16_SNORM}), // Short + f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT}), // Float + f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT}), // Invalid + f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT}), // Invalid + f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT}), // Invalid + }; + + static constexpr Common::EnumMap + integer_type_lookup = { + f({VK_FORMAT_R8_UINT, VK_FORMAT_R8G8_UINT, VK_FORMAT_R8G8B8_UINT, + VK_FORMAT_R8G8B8A8_UINT}), // UByte + f({VK_FORMAT_R8_SINT, VK_FORMAT_R8G8_SINT, VK_FORMAT_R8G8B8_SINT, + VK_FORMAT_R8G8B8A8_SINT}), // Byte + f({VK_FORMAT_R16_UINT, VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16B16_UINT, + VK_FORMAT_R16G16B16A16_UINT}), // UShort + f({VK_FORMAT_R16_SINT, VK_FORMAT_R16G16_SINT, VK_FORMAT_R16G16B16_SINT, + VK_FORMAT_R16G16B16A16_SINT}), // Short + f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT}), // Float + f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT}), // Invalid + f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT}), // Invalid + f({VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_SFLOAT}), // Invalid + }; ASSERT(components > 0 && components <= 4); return integer ? integer_type_lookup[t][components - 1] : float_type_lookup[t][components - 1]; diff --git a/Source/Core/VideoCommon/CPMemory.h b/Source/Core/VideoCommon/CPMemory.h index 1d55d7bf3cfd..63e5e2f2c35c 100644 --- a/Source/Core/VideoCommon/CPMemory.h +++ b/Source/Core/VideoCommon/CPMemory.h @@ -122,7 +122,16 @@ enum class ComponentFormat UShort = 2, // Invalid for normals Short = 3, Float = 4, -}; + // Known to be used by Fifa Street and Def Jam: Fight for New York + // See https://bugs.dolphin-emu.org/issues/12719 + // Assumed to behave the same as float, but further testing is needed + InvalidFloat5 = 5, + // Not known to be used + InvalidFloat6 = 6, + InvalidFloat7 = 7, +}; +// NOTE: don't include the invalid formats here, so that EnumFormatter marks them as invalid +// (EnumFormatter also handles bounds-checking). template <> struct fmt::formatter : EnumFormatter { @@ -141,6 +150,9 @@ constexpr u32 GetElementSize(ComponentFormat format) case ComponentFormat::Short: return 2; case ComponentFormat::Float: + case ComponentFormat::InvalidFloat5: + case ComponentFormat::InvalidFloat6: + case ComponentFormat::InvalidFloat7: return 4; default: PanicAlertFmt("Unknown format {}", format); diff --git a/Source/Core/VideoCommon/VertexLoaderARM64.cpp b/Source/Core/VideoCommon/VertexLoaderARM64.cpp index 2198b0b4270e..9fd8c0c29c8c 100644 --- a/Source/Core/VideoCommon/VertexLoaderARM64.cpp +++ b/Source/Core/VideoCommon/VertexLoaderARM64.cpp @@ -116,7 +116,7 @@ void VertexLoaderARM64::ReadVertex(VertexComponentFormat attribute, ComponentFor m_float_emit.LDUR(load_size, coords, reg, offset); - if (format != ComponentFormat::Float) + if (format < ComponentFormat::Float) { // Extend and convert to float switch (format) @@ -394,8 +394,8 @@ void VertexLoaderARM64::GenerateVertexLoader() if (m_VtxDesc.low.Normal != VertexComponentFormat::NotPresent) { - static constexpr Common::EnumMap(7)> SCALE_MAP = {7, 6, 15, 14, - 0, 0, 0, 0}; + static constexpr Common::EnumMap SCALE_MAP = {7, 6, 15, 14, + 0, 0, 0, 0}; const u8 scaling_exponent = SCALE_MAP[m_VtxAttr.g0.NormalFormat]; // Normal diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp index 5da66c273d81..8ae9a9aa46c0 100644 --- a/Source/Core/VideoCommon/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp @@ -319,6 +319,51 @@ static void CheckCPConfiguration(int vtx_attr_group) DolphinAnalytics::Instance().ReportGameQuirk( GameQuirk::MISMATCHED_GPU_MATRIX_INDICES_BETWEEN_CP_AND_XF); } + + if (g_main_cp_state.vtx_attr[vtx_attr_group].g0.PosFormat >= ComponentFormat::InvalidFloat5) + { + WARN_LOG_FMT(VIDEO, "Invalid position format {} for VAT {} - {:08x} {:08x} {:08x}", + g_main_cp_state.vtx_attr[vtx_attr_group].g0.PosFormat, vtx_attr_group, + g_main_cp_state.vtx_attr[vtx_attr_group].g0.Hex, + g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex, + g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::INVALID_POSITION_COMPONENT_FORMAT); + } + if (g_main_cp_state.vtx_attr[vtx_attr_group].g0.NormalFormat >= ComponentFormat::InvalidFloat5) + { + WARN_LOG_FMT(VIDEO, "Invalid normal format {} for VAT {} - {:08x} {:08x} {:08x}", + g_main_cp_state.vtx_attr[vtx_attr_group].g0.NormalFormat, vtx_attr_group, + g_main_cp_state.vtx_attr[vtx_attr_group].g0.Hex, + g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex, + g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::INVALID_NORMAL_COMPONENT_FORMAT); + } + for (size_t i = 0; i < 8; i++) + { + if (g_main_cp_state.vtx_attr[vtx_attr_group].GetTexFormat(i) >= ComponentFormat::InvalidFloat5) + { + WARN_LOG_FMT(VIDEO, + "Invalid texture coordinate {} format {} for VAT {} - {:08x} {:08x} {:08x}", i, + g_main_cp_state.vtx_attr[vtx_attr_group].GetTexFormat(i), vtx_attr_group, + g_main_cp_state.vtx_attr[vtx_attr_group].g0.Hex, + g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex, + g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex); + DolphinAnalytics::Instance().ReportGameQuirk( + GameQuirk::INVALID_TEXTURE_COORDINATE_COMPONENT_FORMAT); + } + } + for (size_t i = 0; i < 2; i++) + { + if (g_main_cp_state.vtx_attr[vtx_attr_group].GetColorFormat(i) > ColorFormat::RGBA8888) + { + WARN_LOG_FMT(VIDEO, "Invalid color {} format {} for VAT {} - {:08x} {:08x} {:08x}", i, + g_main_cp_state.vtx_attr[vtx_attr_group].GetColorFormat(i), vtx_attr_group, + g_main_cp_state.vtx_attr[vtx_attr_group].g0.Hex, + g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex, + g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::INVALID_COLOR_COMPONENT_FORMAT); + } + } } template diff --git a/Source/Core/VideoCommon/VertexLoaderX64.cpp b/Source/Core/VideoCommon/VertexLoaderX64.cpp index 9aba5a58c8d1..9934570b55a5 100644 --- a/Source/Core/VideoCommon/VertexLoaderX64.cpp +++ b/Source/Core/VideoCommon/VertexLoaderX64.cpp @@ -83,22 +83,32 @@ void VertexLoaderX64::ReadVertex(OpArg data, VertexComponentFormat attribute, bool dequantize, u8 scaling_exponent, AttributeFormat* native_format) { - static const __m128i shuffle_lut[5][3] = { - {_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFF00L), // 1x u8 - _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFF01L, 0xFFFFFF00L), // 2x u8 - _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFF02L, 0xFFFFFF01L, 0xFFFFFF00L)}, // 3x u8 - {_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x00FFFFFFL), // 1x s8 - _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x01FFFFFFL, 0x00FFFFFFL), // 2x s8 - _mm_set_epi32(0xFFFFFFFFL, 0x02FFFFFFL, 0x01FFFFFFL, 0x00FFFFFFL)}, // 3x s8 - {_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFF0001L), // 1x u16 - _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFF0203L, 0xFFFF0001L), // 2x u16 - _mm_set_epi32(0xFFFFFFFFL, 0xFFFF0405L, 0xFFFF0203L, 0xFFFF0001L)}, // 3x u16 - {_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x0001FFFFL), // 1x s16 - _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x0203FFFFL, 0x0001FFFFL), // 2x s16 - _mm_set_epi32(0xFFFFFFFFL, 0x0405FFFFL, 0x0203FFFFL, 0x0001FFFFL)}, // 3x s16 - {_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x00010203L), // 1x float - _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L), // 2x float - _mm_set_epi32(0xFFFFFFFFL, 0x08090A0BL, 0x04050607L, 0x00010203L)}, // 3x float + using ShuffleRow = std::array<__m128i, 3>; + static const Common::EnumMap shuffle_lut = { + ShuffleRow{_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFF00L), // 1x u8 + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFF01L, 0xFFFFFF00L), // 2x u8 + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFF02L, 0xFFFFFF01L, 0xFFFFFF00L)}, // 3x u8 + ShuffleRow{_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x00FFFFFFL), // 1x s8 + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x01FFFFFFL, 0x00FFFFFFL), // 2x s8 + _mm_set_epi32(0xFFFFFFFFL, 0x02FFFFFFL, 0x01FFFFFFL, 0x00FFFFFFL)}, // 3x s8 + ShuffleRow{_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFF0001L), // 1x u16 + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFF0203L, 0xFFFF0001L), // 2x u16 + _mm_set_epi32(0xFFFFFFFFL, 0xFFFF0405L, 0xFFFF0203L, 0xFFFF0001L)}, // 3x u16 + ShuffleRow{_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x0001FFFFL), // 1x s16 + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x0203FFFFL, 0x0001FFFFL), // 2x s16 + _mm_set_epi32(0xFFFFFFFFL, 0x0405FFFFL, 0x0203FFFFL, 0x0001FFFFL)}, // 3x s16 + ShuffleRow{_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x00010203L), // 1x float + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L), // 2x float + _mm_set_epi32(0xFFFFFFFFL, 0x08090A0BL, 0x04050607L, 0x00010203L)}, // 3x float + ShuffleRow{_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x00010203L), // 1x invalid + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L), // 2x invalid + _mm_set_epi32(0xFFFFFFFFL, 0x08090A0BL, 0x04050607L, 0x00010203L)}, // 3x invalid + ShuffleRow{_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x00010203L), // 1x invalid + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L), // 2x invalid + _mm_set_epi32(0xFFFFFFFFL, 0x08090A0BL, 0x04050607L, 0x00010203L)}, // 3x invalid + ShuffleRow{_mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x00010203L), // 1x invalid + _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L), // 2x invalid + _mm_set_epi32(0xFFFFFFFFL, 0x08090A0BL, 0x04050607L, 0x00010203L)}, // 3x invalid }; static const __m128 scale_factors[32] = { _mm_set_ps1(1. / (1u << 0)), _mm_set_ps1(1. / (1u << 1)), _mm_set_ps1(1. / (1u << 2)), @@ -169,7 +179,7 @@ void VertexLoaderX64::ReadVertex(OpArg data, VertexComponentFormat attribute, else MOVD_xmm(coords, data); - PSHUFB(coords, MPIC(&shuffle_lut[u32(format)][count_in - 1])); + PSHUFB(coords, MPIC(&shuffle_lut[format][count_in - 1])); // Sign-extend. if (format == ComponentFormat::Byte) @@ -221,6 +231,9 @@ void VertexLoaderX64::ReadVertex(OpArg data, VertexComponentFormat attribute, PSRLD(coords, 16); break; case ComponentFormat::Float: + case ComponentFormat::InvalidFloat5: + case ComponentFormat::InvalidFloat6: + case ComponentFormat::InvalidFloat7: // Floats don't need to be scaled or converted, // so we can just load/swap/store them directly // and return early. @@ -254,7 +267,7 @@ void VertexLoaderX64::ReadVertex(OpArg data, VertexComponentFormat attribute, } } - if (format != ComponentFormat::Float) + if (format < ComponentFormat::Float) { CVTDQ2PS(coords, R(coords)); @@ -458,8 +471,8 @@ void VertexLoaderX64::GenerateVertexLoader() if (m_VtxDesc.low.Normal != VertexComponentFormat::NotPresent) { - static constexpr Common::EnumMap(7)> SCALE_MAP = {7, 6, 15, 14, - 0, 0, 0, 0}; + static constexpr Common::EnumMap SCALE_MAP = {7, 6, 15, 14, + 0, 0, 0, 0}; const u8 scaling_exponent = SCALE_MAP[m_VtxAttr.g0.NormalFormat]; // Normal diff --git a/Source/Core/VideoCommon/VertexLoader_Normal.cpp b/Source/Core/VideoCommon/VertexLoader_Normal.cpp index abb6d27da7f6..b91c7fe12744 100644 --- a/Source/Core/VideoCommon/VertexLoader_Normal.cpp +++ b/Source/Core/VideoCommon/VertexLoader_Normal.cpp @@ -95,7 +95,7 @@ void Normal_ReadIndex_Indices3(VertexLoader* loader) } using Common::EnumMap; -using Formats = EnumMap; +using Formats = EnumMap; using Elements = EnumMap; using Indices = std::array; using Types = EnumMap; @@ -113,11 +113,17 @@ consteval Types InitializeTable() table[VCF::Direct][false][NCC::N][FMT::UShort] = Normal_ReadDirect; table[VCF::Direct][false][NCC::N][FMT::Short] = Normal_ReadDirect; table[VCF::Direct][false][NCC::N][FMT::Float] = Normal_ReadDirect; + table[VCF::Direct][false][NCC::N][FMT::InvalidFloat5] = Normal_ReadDirect; + table[VCF::Direct][false][NCC::N][FMT::InvalidFloat6] = Normal_ReadDirect; + table[VCF::Direct][false][NCC::N][FMT::InvalidFloat7] = Normal_ReadDirect; table[VCF::Direct][false][NCC::NTB][FMT::UByte] = Normal_ReadDirect; table[VCF::Direct][false][NCC::NTB][FMT::Byte] = Normal_ReadDirect; table[VCF::Direct][false][NCC::NTB][FMT::UShort] = Normal_ReadDirect; table[VCF::Direct][false][NCC::NTB][FMT::Short] = Normal_ReadDirect; table[VCF::Direct][false][NCC::NTB][FMT::Float] = Normal_ReadDirect; + table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadDirect; + table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadDirect; + table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadDirect; // Same as above, since there are no indices table[VCF::Direct][true][NCC::N][FMT::UByte] = Normal_ReadDirect; @@ -125,22 +131,34 @@ consteval Types InitializeTable() table[VCF::Direct][true][NCC::N][FMT::UShort] = Normal_ReadDirect; table[VCF::Direct][true][NCC::N][FMT::Short] = Normal_ReadDirect; table[VCF::Direct][true][NCC::N][FMT::Float] = Normal_ReadDirect; + table[VCF::Direct][true][NCC::N][FMT::InvalidFloat5] = Normal_ReadDirect; + table[VCF::Direct][true][NCC::N][FMT::InvalidFloat6] = Normal_ReadDirect; + table[VCF::Direct][true][NCC::N][FMT::InvalidFloat7] = Normal_ReadDirect; table[VCF::Direct][true][NCC::NTB][FMT::UByte] = Normal_ReadDirect; table[VCF::Direct][true][NCC::NTB][FMT::Byte] = Normal_ReadDirect; table[VCF::Direct][true][NCC::NTB][FMT::UShort] = Normal_ReadDirect; table[VCF::Direct][true][NCC::NTB][FMT::Short] = Normal_ReadDirect; table[VCF::Direct][true][NCC::NTB][FMT::Float] = Normal_ReadDirect; + table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadDirect; + table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadDirect; + table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadDirect; table[VCF::Index8][false][NCC::N][FMT::UByte] = Normal_ReadIndex; table[VCF::Index8][false][NCC::N][FMT::Byte] = Normal_ReadIndex; table[VCF::Index8][false][NCC::N][FMT::UShort] = Normal_ReadIndex; table[VCF::Index8][false][NCC::N][FMT::Short] = Normal_ReadIndex; table[VCF::Index8][false][NCC::N][FMT::Float] = Normal_ReadIndex; + table[VCF::Index8][false][NCC::N][FMT::InvalidFloat5] = Normal_ReadIndex; + table[VCF::Index8][false][NCC::N][FMT::InvalidFloat6] = Normal_ReadIndex; + table[VCF::Index8][false][NCC::N][FMT::InvalidFloat7] = Normal_ReadIndex; table[VCF::Index8][false][NCC::NTB][FMT::UByte] = Normal_ReadIndex; table[VCF::Index8][false][NCC::NTB][FMT::Byte] = Normal_ReadIndex; table[VCF::Index8][false][NCC::NTB][FMT::UShort] = Normal_ReadIndex; table[VCF::Index8][false][NCC::NTB][FMT::Short] = Normal_ReadIndex; table[VCF::Index8][false][NCC::NTB][FMT::Float] = Normal_ReadIndex; + table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadIndex; + table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadIndex; + table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadIndex; // Same for NormalComponentCount::N; differs for NTB table[VCF::Index8][true][NCC::N][FMT::UByte] = Normal_ReadIndex; @@ -148,22 +166,34 @@ consteval Types InitializeTable() table[VCF::Index8][true][NCC::N][FMT::UShort] = Normal_ReadIndex; table[VCF::Index8][true][NCC::N][FMT::Short] = Normal_ReadIndex; table[VCF::Index8][true][NCC::N][FMT::Float] = Normal_ReadIndex; + table[VCF::Index8][true][NCC::N][FMT::InvalidFloat5] = Normal_ReadIndex; + table[VCF::Index8][true][NCC::N][FMT::InvalidFloat6] = Normal_ReadIndex; + table[VCF::Index8][true][NCC::N][FMT::InvalidFloat7] = Normal_ReadIndex; table[VCF::Index8][true][NCC::NTB][FMT::UByte] = Normal_ReadIndex_Indices3; table[VCF::Index8][true][NCC::NTB][FMT::Byte] = Normal_ReadIndex_Indices3; table[VCF::Index8][true][NCC::NTB][FMT::UShort] = Normal_ReadIndex_Indices3; table[VCF::Index8][true][NCC::NTB][FMT::Short] = Normal_ReadIndex_Indices3; table[VCF::Index8][true][NCC::NTB][FMT::Float] = Normal_ReadIndex_Indices3; + table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadIndex_Indices3; + table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadIndex_Indices3; + table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadIndex_Indices3; table[VCF::Index16][false][NCC::N][FMT::UByte] = Normal_ReadIndex; table[VCF::Index16][false][NCC::N][FMT::Byte] = Normal_ReadIndex; table[VCF::Index16][false][NCC::N][FMT::UShort] = Normal_ReadIndex; table[VCF::Index16][false][NCC::N][FMT::Short] = Normal_ReadIndex; table[VCF::Index16][false][NCC::N][FMT::Float] = Normal_ReadIndex; + table[VCF::Index16][false][NCC::N][FMT::InvalidFloat5] = Normal_ReadIndex; + table[VCF::Index16][false][NCC::N][FMT::InvalidFloat6] = Normal_ReadIndex; + table[VCF::Index16][false][NCC::N][FMT::InvalidFloat7] = Normal_ReadIndex; table[VCF::Index16][false][NCC::NTB][FMT::UByte] = Normal_ReadIndex; table[VCF::Index16][false][NCC::NTB][FMT::Byte] = Normal_ReadIndex; table[VCF::Index16][false][NCC::NTB][FMT::UShort] = Normal_ReadIndex; table[VCF::Index16][false][NCC::NTB][FMT::Short] = Normal_ReadIndex; table[VCF::Index16][false][NCC::NTB][FMT::Float] = Normal_ReadIndex; + table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadIndex; + table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadIndex; + table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadIndex; // Same for NormalComponentCount::N; differs for NTB table[VCF::Index16][true][NCC::N][FMT::UByte] = Normal_ReadIndex; @@ -171,11 +201,17 @@ consteval Types InitializeTable() table[VCF::Index16][true][NCC::N][FMT::UShort] = Normal_ReadIndex; table[VCF::Index16][true][NCC::N][FMT::Short] = Normal_ReadIndex; table[VCF::Index16][true][NCC::N][FMT::Float] = Normal_ReadIndex; + table[VCF::Index16][true][NCC::N][FMT::InvalidFloat5] = Normal_ReadIndex; + table[VCF::Index16][true][NCC::N][FMT::InvalidFloat6] = Normal_ReadIndex; + table[VCF::Index16][true][NCC::N][FMT::InvalidFloat7] = Normal_ReadIndex; table[VCF::Index16][true][NCC::NTB][FMT::UByte] = Normal_ReadIndex_Indices3; table[VCF::Index16][true][NCC::NTB][FMT::Byte] = Normal_ReadIndex_Indices3; table[VCF::Index16][true][NCC::NTB][FMT::UShort] = Normal_ReadIndex_Indices3; table[VCF::Index16][true][NCC::NTB][FMT::Short] = Normal_ReadIndex_Indices3; table[VCF::Index16][true][NCC::NTB][FMT::Float] = Normal_ReadIndex_Indices3; + table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat5] = Normal_ReadIndex_Indices3; + table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat6] = Normal_ReadIndex_Indices3; + table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat7] = Normal_ReadIndex_Indices3; return table; } diff --git a/Source/Core/VideoCommon/VertexLoader_Normal.h b/Source/Core/VideoCommon/VertexLoader_Normal.h index b5200dc8755c..0b8c10776522 100644 --- a/Source/Core/VideoCommon/VertexLoader_Normal.h +++ b/Source/Core/VideoCommon/VertexLoader_Normal.h @@ -27,7 +27,8 @@ class VertexLoader_Normal using EnumMap = typename Common::EnumMap; using SizeTable = EnumMap< - std::array, NormalComponentCount::NTB>, 2>, + std::array, NormalComponentCount::NTB>, + 2>, VertexComponentFormat::Index16>; static constexpr SizeTable s_table_size = []() consteval @@ -43,11 +44,17 @@ class VertexLoader_Normal table[VCF::Direct][false][NCC::N][FMT::UShort] = 6; table[VCF::Direct][false][NCC::N][FMT::Short] = 6; table[VCF::Direct][false][NCC::N][FMT::Float] = 12; + table[VCF::Direct][false][NCC::N][FMT::InvalidFloat5] = 12; + table[VCF::Direct][false][NCC::N][FMT::InvalidFloat6] = 12; + table[VCF::Direct][false][NCC::N][FMT::InvalidFloat7] = 12; table[VCF::Direct][false][NCC::NTB][FMT::UByte] = 9; table[VCF::Direct][false][NCC::NTB][FMT::Byte] = 9; table[VCF::Direct][false][NCC::NTB][FMT::UShort] = 18; table[VCF::Direct][false][NCC::NTB][FMT::Short] = 18; table[VCF::Direct][false][NCC::NTB][FMT::Float] = 36; + table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat5] = 36; + table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat6] = 36; + table[VCF::Direct][false][NCC::NTB][FMT::InvalidFloat7] = 36; // Same as above, since there are no indices table[VCF::Direct][true][NCC::N][FMT::UByte] = 3; @@ -55,22 +62,34 @@ class VertexLoader_Normal table[VCF::Direct][true][NCC::N][FMT::UShort] = 6; table[VCF::Direct][true][NCC::N][FMT::Short] = 6; table[VCF::Direct][true][NCC::N][FMT::Float] = 12; + table[VCF::Direct][true][NCC::N][FMT::InvalidFloat5] = 12; + table[VCF::Direct][true][NCC::N][FMT::InvalidFloat6] = 12; + table[VCF::Direct][true][NCC::N][FMT::InvalidFloat7] = 12; table[VCF::Direct][true][NCC::NTB][FMT::UByte] = 9; table[VCF::Direct][true][NCC::NTB][FMT::Byte] = 9; table[VCF::Direct][true][NCC::NTB][FMT::UShort] = 18; table[VCF::Direct][true][NCC::NTB][FMT::Short] = 18; table[VCF::Direct][true][NCC::NTB][FMT::Float] = 36; + table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat5] = 36; + table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat6] = 36; + table[VCF::Direct][true][NCC::NTB][FMT::InvalidFloat7] = 36; table[VCF::Index8][false][NCC::N][FMT::UByte] = 1; table[VCF::Index8][false][NCC::N][FMT::Byte] = 1; table[VCF::Index8][false][NCC::N][FMT::UShort] = 1; table[VCF::Index8][false][NCC::N][FMT::Short] = 1; table[VCF::Index8][false][NCC::N][FMT::Float] = 1; + table[VCF::Index8][false][NCC::N][FMT::InvalidFloat5] = 1; + table[VCF::Index8][false][NCC::N][FMT::InvalidFloat6] = 1; + table[VCF::Index8][false][NCC::N][FMT::InvalidFloat7] = 1; table[VCF::Index8][false][NCC::NTB][FMT::UByte] = 1; table[VCF::Index8][false][NCC::NTB][FMT::Byte] = 1; table[VCF::Index8][false][NCC::NTB][FMT::UShort] = 1; table[VCF::Index8][false][NCC::NTB][FMT::Short] = 1; table[VCF::Index8][false][NCC::NTB][FMT::Float] = 1; + table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat5] = 1; + table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat6] = 1; + table[VCF::Index8][false][NCC::NTB][FMT::InvalidFloat7] = 1; // Same for NormalComponentCount::N; differs for NTB table[VCF::Index8][true][NCC::N][FMT::UByte] = 1; @@ -78,22 +97,34 @@ class VertexLoader_Normal table[VCF::Index8][true][NCC::N][FMT::UShort] = 1; table[VCF::Index8][true][NCC::N][FMT::Short] = 1; table[VCF::Index8][true][NCC::N][FMT::Float] = 1; + table[VCF::Index8][true][NCC::N][FMT::InvalidFloat5] = 1; + table[VCF::Index8][true][NCC::N][FMT::InvalidFloat6] = 1; + table[VCF::Index8][true][NCC::N][FMT::InvalidFloat7] = 1; table[VCF::Index8][true][NCC::NTB][FMT::UByte] = 3; table[VCF::Index8][true][NCC::NTB][FMT::Byte] = 3; table[VCF::Index8][true][NCC::NTB][FMT::UShort] = 3; table[VCF::Index8][true][NCC::NTB][FMT::Short] = 3; table[VCF::Index8][true][NCC::NTB][FMT::Float] = 3; + table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat5] = 3; + table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat6] = 3; + table[VCF::Index8][true][NCC::NTB][FMT::InvalidFloat7] = 3; table[VCF::Index16][false][NCC::N][FMT::UByte] = 2; table[VCF::Index16][false][NCC::N][FMT::Byte] = 2; table[VCF::Index16][false][NCC::N][FMT::UShort] = 2; table[VCF::Index16][false][NCC::N][FMT::Short] = 2; table[VCF::Index16][false][NCC::N][FMT::Float] = 2; + table[VCF::Index16][false][NCC::N][FMT::InvalidFloat5] = 2; + table[VCF::Index16][false][NCC::N][FMT::InvalidFloat6] = 2; + table[VCF::Index16][false][NCC::N][FMT::InvalidFloat7] = 2; table[VCF::Index16][false][NCC::NTB][FMT::UByte] = 2; table[VCF::Index16][false][NCC::NTB][FMT::Byte] = 2; table[VCF::Index16][false][NCC::NTB][FMT::UShort] = 2; table[VCF::Index16][false][NCC::NTB][FMT::Short] = 2; table[VCF::Index16][false][NCC::NTB][FMT::Float] = 2; + table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat5] = 2; + table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat6] = 2; + table[VCF::Index16][false][NCC::NTB][FMT::InvalidFloat7] = 2; // Same for NormalComponentCount::N; differs for NTB table[VCF::Index16][true][NCC::N][FMT::UByte] = 2; @@ -101,11 +132,17 @@ class VertexLoader_Normal table[VCF::Index16][true][NCC::N][FMT::UShort] = 2; table[VCF::Index16][true][NCC::N][FMT::Short] = 2; table[VCF::Index16][true][NCC::N][FMT::Float] = 2; + table[VCF::Index16][true][NCC::N][FMT::InvalidFloat5] = 2; + table[VCF::Index16][true][NCC::N][FMT::InvalidFloat6] = 2; + table[VCF::Index16][true][NCC::N][FMT::InvalidFloat7] = 2; table[VCF::Index16][true][NCC::NTB][FMT::UByte] = 6; table[VCF::Index16][true][NCC::NTB][FMT::Byte] = 6; table[VCF::Index16][true][NCC::NTB][FMT::UShort] = 6; table[VCF::Index16][true][NCC::NTB][FMT::Short] = 6; table[VCF::Index16][true][NCC::NTB][FMT::Float] = 6; + table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat5] = 6; + table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat6] = 6; + table[VCF::Index16][true][NCC::NTB][FMT::InvalidFloat7] = 6; return table; } diff --git a/Source/Core/VideoCommon/VertexLoader_Position.cpp b/Source/Core/VideoCommon/VertexLoader_Position.cpp index 946dacdde1d4..27ea61ea3007 100644 --- a/Source/Core/VideoCommon/VertexLoader_Position.cpp +++ b/Source/Core/VideoCommon/VertexLoader_Position.cpp @@ -71,7 +71,7 @@ void Pos_ReadIndex(VertexLoader* loader) } using ComponentCountRow = Common::EnumMap; -using ComponentFormatTable = Common::EnumMap; +using ComponentFormatTable = Common::EnumMap; using Table = Common::EnumMap; constexpr Table s_table_read_position = { @@ -81,6 +81,9 @@ constexpr Table s_table_read_position = { ComponentCountRow(nullptr, nullptr), ComponentCountRow(nullptr, nullptr), ComponentCountRow(nullptr, nullptr), + ComponentCountRow(nullptr, nullptr), + ComponentCountRow(nullptr, nullptr), + ComponentCountRow(nullptr, nullptr), }), ComponentFormatTable({ ComponentCountRow(Pos_ReadDirect, Pos_ReadDirect), @@ -88,6 +91,9 @@ constexpr Table s_table_read_position = { ComponentCountRow(Pos_ReadDirect, Pos_ReadDirect), ComponentCountRow(Pos_ReadDirect, Pos_ReadDirect), ComponentCountRow(Pos_ReadDirect, Pos_ReadDirect), + ComponentCountRow(Pos_ReadDirect, Pos_ReadDirect), + ComponentCountRow(Pos_ReadDirect, Pos_ReadDirect), + ComponentCountRow(Pos_ReadDirect, Pos_ReadDirect), }), ComponentFormatTable({ ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), @@ -95,6 +101,9 @@ constexpr Table s_table_read_position = { ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), + ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), + ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), + ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), }), ComponentFormatTable({ ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), @@ -102,6 +111,9 @@ constexpr Table s_table_read_position = { ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), + ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), + ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), + ComponentCountRow(Pos_ReadIndex, Pos_ReadIndex), }), }; } // Anonymous namespace diff --git a/Source/Core/VideoCommon/VertexLoader_Position.h b/Source/Core/VideoCommon/VertexLoader_Position.h index da095419fda7..710e5eee6a85 100644 --- a/Source/Core/VideoCommon/VertexLoader_Position.h +++ b/Source/Core/VideoCommon/VertexLoader_Position.h @@ -26,8 +26,9 @@ class VertexLoader_Position template using EnumMap = typename Common::EnumMap; - using SizeTable = EnumMap, ComponentFormat::Float>, - VertexComponentFormat::Index16>; + using SizeTable = + EnumMap, ComponentFormat::InvalidFloat7>, + VertexComponentFormat::Index16>; static constexpr SizeTable s_table_size = []() consteval { @@ -41,18 +42,27 @@ class VertexLoader_Position table[VCF::Direct][FMT::UShort] = {4, 6}; table[VCF::Direct][FMT::Short] = {4, 6}; table[VCF::Direct][FMT::Float] = {8, 12}; + table[VCF::Direct][FMT::InvalidFloat5] = {8, 12}; + table[VCF::Direct][FMT::InvalidFloat6] = {8, 12}; + table[VCF::Direct][FMT::InvalidFloat7] = {8, 12}; table[VCF::Index8][FMT::UByte] = {1, 1}; table[VCF::Index8][FMT::Byte] = {1, 1}; table[VCF::Index8][FMT::UShort] = {1, 1}; table[VCF::Index8][FMT::Short] = {1, 1}; table[VCF::Index8][FMT::Float] = {1, 1}; + table[VCF::Index8][FMT::InvalidFloat5] = {1, 1}; + table[VCF::Index8][FMT::InvalidFloat6] = {1, 1}; + table[VCF::Index8][FMT::InvalidFloat7] = {1, 1}; table[VCF::Index16][FMT::UByte] = {2, 2}; table[VCF::Index16][FMT::Byte] = {2, 2}; table[VCF::Index16][FMT::UShort] = {2, 2}; table[VCF::Index16][FMT::Short] = {2, 2}; table[VCF::Index16][FMT::Float] = {2, 2}; + table[VCF::Index16][FMT::InvalidFloat5] = {2, 2}; + table[VCF::Index16][FMT::InvalidFloat6] = {2, 2}; + table[VCF::Index16][FMT::InvalidFloat7] = {2, 2}; return table; } diff --git a/Source/Core/VideoCommon/VertexLoader_TextCoord.cpp b/Source/Core/VideoCommon/VertexLoader_TextCoord.cpp index fcb2982e6fd0..2d2766a7eadc 100644 --- a/Source/Core/VideoCommon/VertexLoader_TextCoord.cpp +++ b/Source/Core/VideoCommon/VertexLoader_TextCoord.cpp @@ -60,7 +60,7 @@ void TexCoord_ReadIndex(VertexLoader* loader) } using ComponentCountRow = Common::EnumMap; -using ComponentFormatTable = Common::EnumMap; +using ComponentFormatTable = Common::EnumMap; using Table = Common::EnumMap; constexpr Table s_table_read_tex_coord = { @@ -70,6 +70,9 @@ constexpr Table s_table_read_tex_coord = { ComponentCountRow(nullptr, nullptr), ComponentCountRow(nullptr, nullptr), ComponentCountRow(nullptr, nullptr), + ComponentCountRow(nullptr, nullptr), + ComponentCountRow(nullptr, nullptr), + ComponentCountRow(nullptr, nullptr), }), ComponentFormatTable({ ComponentCountRow(TexCoord_ReadDirect, TexCoord_ReadDirect), @@ -77,6 +80,9 @@ constexpr Table s_table_read_tex_coord = { ComponentCountRow(TexCoord_ReadDirect, TexCoord_ReadDirect), ComponentCountRow(TexCoord_ReadDirect, TexCoord_ReadDirect), ComponentCountRow(TexCoord_ReadDirect, TexCoord_ReadDirect), + ComponentCountRow(TexCoord_ReadDirect, TexCoord_ReadDirect), + ComponentCountRow(TexCoord_ReadDirect, TexCoord_ReadDirect), + ComponentCountRow(TexCoord_ReadDirect, TexCoord_ReadDirect), }), ComponentFormatTable({ ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), @@ -84,6 +90,9 @@ constexpr Table s_table_read_tex_coord = { ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), + ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), + ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), + ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), }), ComponentFormatTable({ ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), @@ -91,6 +100,9 @@ constexpr Table s_table_read_tex_coord = { ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), + ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), + ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), + ComponentCountRow(TexCoord_ReadIndex, TexCoord_ReadIndex), }), }; } // Anonymous namespace diff --git a/Source/Core/VideoCommon/VertexLoader_TextCoord.h b/Source/Core/VideoCommon/VertexLoader_TextCoord.h index c71688e1e2b0..5593571f07a1 100644 --- a/Source/Core/VideoCommon/VertexLoader_TextCoord.h +++ b/Source/Core/VideoCommon/VertexLoader_TextCoord.h @@ -29,8 +29,9 @@ class VertexLoader_TextCoord template using EnumMap = typename Common::EnumMap; - using SizeTable = EnumMap, ComponentFormat::Float>, - VertexComponentFormat::Index16>; + using SizeTable = + EnumMap, ComponentFormat::InvalidFloat7>, + VertexComponentFormat::Index16>; static constexpr SizeTable s_table_size = []() consteval { @@ -44,18 +45,27 @@ class VertexLoader_TextCoord table[VCF::Direct][FMT::UShort] = {2, 4}; table[VCF::Direct][FMT::Short] = {2, 4}; table[VCF::Direct][FMT::Float] = {4, 8}; + table[VCF::Direct][FMT::InvalidFloat5] = {4, 8}; + table[VCF::Direct][FMT::InvalidFloat6] = {4, 8}; + table[VCF::Direct][FMT::InvalidFloat7] = {4, 8}; table[VCF::Index8][FMT::UByte] = {1, 1}; table[VCF::Index8][FMT::Byte] = {1, 1}; table[VCF::Index8][FMT::UShort] = {1, 1}; table[VCF::Index8][FMT::Short] = {1, 1}; table[VCF::Index8][FMT::Float] = {1, 1}; + table[VCF::Index8][FMT::InvalidFloat5] = {1, 1}; + table[VCF::Index8][FMT::InvalidFloat6] = {1, 1}; + table[VCF::Index8][FMT::InvalidFloat7] = {1, 1}; table[VCF::Index16][FMT::UByte] = {2, 2}; table[VCF::Index16][FMT::Byte] = {2, 2}; table[VCF::Index16][FMT::UShort] = {2, 2}; table[VCF::Index16][FMT::Short] = {2, 2}; table[VCF::Index16][FMT::Float] = {2, 2}; + table[VCF::Index16][FMT::InvalidFloat5] = {2, 2}; + table[VCF::Index16][FMT::InvalidFloat6] = {2, 2}; + table[VCF::Index16][FMT::InvalidFloat7] = {2, 2}; return table; } diff --git a/Source/UnitTests/VideoCommon/VertexLoaderTest.cpp b/Source/UnitTests/VideoCommon/VertexLoaderTest.cpp index 24f975d8fc38..eedbff0304a3 100644 --- a/Source/UnitTests/VideoCommon/VertexLoaderTest.cpp +++ b/Source/UnitTests/VideoCommon/VertexLoaderTest.cpp @@ -121,7 +121,9 @@ INSTANTIATE_TEST_SUITE_P( ::testing::Values(VertexComponentFormat::Direct, VertexComponentFormat::Index8, VertexComponentFormat::Index16), ::testing::Values(ComponentFormat::UByte, ComponentFormat::Byte, ComponentFormat::UShort, - ComponentFormat::Short, ComponentFormat::Float), + ComponentFormat::Short, ComponentFormat::Float, + ComponentFormat::InvalidFloat5, ComponentFormat::InvalidFloat6, + ComponentFormat::InvalidFloat7), ::testing::Values(CoordComponentCount::XY, CoordComponentCount::XYZ), ::testing::Values(0, 1, 31) // frac )); @@ -170,10 +172,12 @@ TEST_P(VertexLoaderParamTest, PositionAll) { input_size = addr == VertexComponentFormat::Index8 ? 1 : 2; for (int i = 0; i < count; i++) + { if (addr == VertexComponentFormat::Index8) Input(i); else Input(i); + } VertexLoaderManager::cached_arraybases[CPArray::Position] = m_src.GetPointer(); g_main_cp_state.array_strides[CPArray::Position] = elem_count * elem_size; } @@ -195,6 +199,9 @@ TEST_P(VertexLoaderParamTest, PositionAll) Input(MathUtil::SaturatingCast(value)); break; case ComponentFormat::Float: + case ComponentFormat::InvalidFloat5: + case ComponentFormat::InvalidFloat6: + case ComponentFormat::InvalidFloat7: Input(value); break; } @@ -202,7 +209,7 @@ TEST_P(VertexLoaderParamTest, PositionAll) RunVertices(count); - float scale = 1.f / (1u << (format == ComponentFormat::Float ? 0 : frac)); + float scale = 1.f / (1u << (format >= ComponentFormat::Float ? 0 : frac)); for (auto iter = values.begin(); iter != values.end();) { float f, g; @@ -225,6 +232,9 @@ TEST_P(VertexLoaderParamTest, PositionAll) g = MathUtil::SaturatingCast(*iter++); break; case ComponentFormat::Float: + case ComponentFormat::InvalidFloat5: + case ComponentFormat::InvalidFloat6: + case ComponentFormat::InvalidFloat7: f = *iter++; g = *iter++; break; @@ -543,7 +553,9 @@ INSTANTIATE_TEST_SUITE_P( ::testing::Values(VertexComponentFormat::NotPresent, VertexComponentFormat::Direct, VertexComponentFormat::Index8, VertexComponentFormat::Index16), ::testing::Values(ComponentFormat::UByte, ComponentFormat::Byte, ComponentFormat::UShort, - ComponentFormat::Short, ComponentFormat::Float), + ComponentFormat::Short, ComponentFormat::Float, + ComponentFormat::InvalidFloat5, ComponentFormat::InvalidFloat6, + ComponentFormat::InvalidFloat7), ::testing::Values(NormalComponentCount::N, NormalComponentCount::NTB), ::testing::Values(false, true))); @@ -609,7 +621,9 @@ TEST_P(VertexLoaderNormalTest, NormalAll) Input(value * (1 << 14)); break; case ComponentFormat::Float: - default: + case ComponentFormat::InvalidFloat5: + case ComponentFormat::InvalidFloat6: + case ComponentFormat::InvalidFloat7: Input(value); break; }