video_core: Rework clear values (#1381)

* Clear color convertion

* Add missing formats

* Add swap handling

* Format bits and offsets

* clang-format

* Make num_components const

* Initialize alpha to 1

* Handle SnormNz as Snorm

* Don0t leave accidental nonzero values

* parallel3 for linux-qt

* Move number_utils to common
This commit is contained in:
Lander Gallastegi 2024-10-16 11:55:45 +02:00 committed by GitHub
parent 170db22d9c
commit 877cda9b9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 561 additions and 62 deletions

View file

@ -432,6 +432,8 @@ set(COMMON src/common/logging/backend.cpp
src/common/version.h
src/common/ntapi.h
src/common/ntapi.cpp
src/common/number_utils.h
src/common/number_utils.cpp
src/common/memory_patcher.h
src/common/memory_patcher.cpp
src/common/scm_rev.cpp
@ -771,7 +773,7 @@ endif()
create_target_directory_groups(shadps4)
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn)
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half)
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3 pugixml::pugixml)
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
@ -794,9 +796,6 @@ if (APPLE)
# Replacement for std::chrono::time_zone
target_link_libraries(shadps4 PRIVATE date::date-tz)
# Half float conversions for F16C patches
target_link_libraries(shadps4 PRIVATE half)
endif()
if (NOT ENABLE_QT_GUI)

View file

@ -141,11 +141,11 @@ if (WIN32)
target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument")
endif()
if (APPLE)
# half
add_library(half INTERFACE)
target_include_directories(half INTERFACE half/include)
# half
add_library(half INTERFACE)
target_include_directories(half INTERFACE half/include)
if (APPLE)
# date
if (NOT TARGET date::date-tz)
option(BUILD_TZ_LIB "" ON)

161
src/common/number_utils.cpp Normal file
View file

@ -0,0 +1,161 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <array>
#include <half.hpp>
#include "common/number_utils.h"
#include "video_core/amdgpu/pixel_format.h"
#include "video_core/amdgpu/types.h"
#define UF11_EXPONENT_SHIFT 6
#define UF10_EXPONENT_SHIFT 5
#define RGB9E5_MANTISSA_BITS 9
#define RGB9E5_EXP_BIAS 1
#define F32_INFINITY 0x7f800000
namespace NumberUtils {
float Uf11ToF32(u16 val) {
union {
float f;
u32 ui;
} f32;
int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT;
int mantissa = (val & 0x003f);
f32.f = 0.0;
if (exponent == 0) {
if (mantissa != 0) {
const float scale = 1.0 / (1 << 20);
f32.f = scale * mantissa;
}
} else if (exponent == 31) {
f32.ui = F32_INFINITY | mantissa;
} else {
float scale, decimal;
exponent -= 15;
if (exponent < 0) {
scale = 1.0f / (1 << -exponent);
} else {
scale = (float)(1 << exponent);
}
decimal = 1.0f + (float)mantissa / 64;
f32.f = scale * decimal;
}
return f32.f;
}
float Uf10ToF32(u16 val) {
union {
float f;
u32 ui;
} f32;
int exponent = (val & 0x03e0) >> UF10_EXPONENT_SHIFT;
int mantissa = (val & 0x001f);
f32.f = 0.0;
if (exponent == 0) {
if (mantissa != 0) {
const float scale = 1.0 / (1 << 19);
f32.f = scale * mantissa;
}
} else if (exponent == 31) {
f32.ui = F32_INFINITY | mantissa;
} else {
float scale, decimal;
exponent -= 15;
if (exponent < 0) {
scale = 1.0f / (1 << -exponent);
} else {
scale = (float)(1 << exponent);
}
decimal = 1.0f + (float)mantissa / 32;
f32.f = scale * decimal;
}
return f32.f;
}
float Uf16ToF32(u16 val) {
return half_float::half_cast<float>(reinterpret_cast<half_float::half&>(val));
}
float U2ToUnorm(u8 val) {
static constexpr auto c = 1.0f / 3.0f;
return float(val * c);
}
float S2ToSnorm(s8 val) {
static constexpr auto c = 1.0f / 1.0f;
return float(val * c);
}
float U4ToUnorm(u8 val) {
static constexpr auto c = 1.0f / 15.0f;
return float(val * c);
}
float S4ToSnorm(s8 val) {
static constexpr auto c = 1.0f / 7.0f;
return float(val * c);
}
float U5ToUnorm(u8 val) {
static constexpr auto c = 1.0f / 31.0f;
return float(val * c);
}
float S5ToSnorm(s8 val) {
static constexpr auto c = 1.0f / 15.0f;
return float(val * c);
}
float U6ToUnorm(u8 val) {
static constexpr auto c = 1.0f / 63.0f;
return float(val * c);
}
float S6ToSnorm(s8 val) {
static constexpr auto c = 1.0f / 31.0f;
return float(val * c);
}
float U8ToUnorm(u8 val) {
static constexpr auto c = 1.0f / 255.0f;
return float(val * c);
}
float S8ToSnorm(s8 val) {
static constexpr auto c = 1.0f / 127.0f;
return float(val * c);
}
float U10ToUnorm(u16 val) {
static constexpr auto c = 1.0f / 1023.0f;
return float(val * c);
}
float S10ToSnorm(s16 val) {
static constexpr auto c = 1.0f / 511.0f;
return float(val * c);
}
float U16ToUnorm(u16 val) {
static constexpr auto c = 1.0f / 65535.0f;
return float(val * c);
}
float S16ToSnorm(s16 val) {
static constexpr auto c = 1.0f / 32767.0f;
return float(val * c);
}
} // namespace NumberUtils

28
src/common/number_utils.h Normal file
View file

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/types.h"
namespace NumberUtils {
float Uf11ToF32(u16 val);
float Uf10ToF32(u16 val);
float Uf16ToF32(u16 val);
float U2ToUnorm(u8 val);
float S2ToSnorm(s8 val);
float U4ToUnorm(u8 val);
float S4ToSnorm(s8 val);
float U5ToUnorm(u8 val);
float S5ToSnorm(s8 val);
float U6ToUnorm(u8 val);
float S6ToSnorm(s8 val);
float U8ToUnorm(u8 val);
float S8ToSnorm(s8 val);
float U10ToUnorm(u16 val);
float S10ToSnorm(s16 val);
float U16ToUnorm(u16 val);
float S16ToSnorm(s16 val);
} // namespace NumberUtils

View file

@ -144,10 +144,10 @@ static constexpr std::array component_bits = {
std::array{8, 8, 0, 0}, // 3 Format8_8
std::array{32, 0, 0, 0}, // 4 Format32
std::array{16, 16, 0, 0}, // 5 Format16_16
std::array{10, 11, 11, 0}, // 6 Format10_11_11
std::array{11, 11, 10, 0}, // 7 Format11_11_10
std::array{10, 10, 10, 2}, // 8 Format10_10_10_2
std::array{2, 10, 10, 10}, // 9 Format2_10_10_10
std::array{11, 11, 10, 0}, // 6 Format10_11_11
std::array{10, 11, 11, 0}, // 7 Format11_11_10
std::array{2, 10, 10, 10}, // 8 Format10_10_10_2
std::array{10, 10, 10, 2}, // 9 Format2_10_10_10
std::array{8, 8, 8, 8}, // 10 Format8_8_8_8
std::array{32, 32, 0, 0}, // 11 Format32_32
std::array{16, 16, 16, 16}, // 12 Format16_16_16_16
@ -155,12 +155,12 @@ static constexpr std::array component_bits = {
std::array{32, 32, 32, 32}, // 14 Format32_32_32_32
std::array{0, 0, 0, 0}, // 15
std::array{5, 6, 5, 0}, // 16 Format5_6_5
std::array{1, 5, 5, 5}, // 17 Format1_5_5_5
std::array{5, 5, 5, 1}, // 18 Format5_5_5_1
std::array{5, 5, 5, 1}, // 17 Format1_5_5_5
std::array{1, 5, 5, 5}, // 18 Format5_5_5_1
std::array{4, 4, 4, 4}, // 19 Format4_4_4_4
std::array{8, 24, 0, 0}, // 20 Format8_24
std::array{24, 8, 0, 0}, // 21 Format24_8
std::array{24, 8, 0, 0}, // 22 FormatX24_8_32
std::array{24, 8, 0, 0}, // 20 Format8_24
std::array{8, 24, 0, 0}, // 21 Format24_8
std::array{8, 24, 0, 0}, // 22 FormatX24_8_32
std::array{0, 0, 0, 0}, // 23
std::array{0, 0, 0, 0}, // 24
std::array{0, 0, 0, 0}, // 25
@ -197,10 +197,10 @@ static constexpr std::array component_offset = {
std::array{0, 8, -1, -1}, // 3 Format8_8
std::array{0, -1, -1, -1}, // 4 Format32
std::array{0, 16, -1, -1}, // 5 Format16_16
std::array{0, 10, 21, -1}, // 6 Format10_11_11
std::array{0, 11, 22, -1}, // 7 Format11_11_10
std::array{0, 10, 20, 30}, // 8 Format10_10_10_2
std::array{0, 2, 12, 22}, // 9 Format2_10_10_10
std::array{0, 11, 22, -1}, // 6 Format10_11_11
std::array{0, 10, 21, -1}, // 7 Format11_11_10
std::array{0, 2, 12, 22}, // 8 Format10_10_10_2
std::array{0, 10, 20, 30}, // 9 Format2_10_10_10
std::array{0, 8, 16, 24}, // 10 Format8_8_8_8
std::array{0, 32, -1, -1}, // 11 Format32_32
std::array{0, 16, 32, 48}, // 12 Format16_16_16_16
@ -208,12 +208,12 @@ static constexpr std::array component_offset = {
std::array{0, 32, 64, 96}, // 14 Format32_32_32_32
std::array{-1, -1, -1, -1}, // 15
std::array{0, 5, 11, -1}, // 16 Format5_6_5
std::array{0, 1, 6, 11}, // 17 Format1_5_5_5
std::array{0, 5, 10, 15}, // 18 Format5_5_5_1
std::array{0, 5, 10, 15}, // 17 Format1_5_5_5
std::array{0, 1, 6, 11}, // 18 Format5_5_5_1
std::array{0, 4, 8, 12}, // 19 Format4_4_4_4
std::array{0, 8, -1, -1}, // 20 Format8_24
std::array{0, 24, -1, -1}, // 21 Format24_8
std::array{0, 24, -1, -1}, // 22 FormatX24_8_32
std::array{0, 24, -1, -1}, // 20 Format8_24
std::array{0, 8, -1, -1}, // 21 Format24_8
std::array{0, 8, -1, -1}, // 22 FormatX24_8_32
std::array{-1, -1, -1, -1}, // 23
std::array{-1, -1, -1, -1}, // 24
std::array{-1, -1, -1, -1}, // 25

View file

@ -2,11 +2,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
#include "common/number_utils.h"
#include "video_core/amdgpu/pixel_format.h"
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
#include <magic_enum.hpp>
#define INVALID_NUMBER_FORMAT_COMBO \
LOG_ERROR(Render_Vulkan, "Unsupported number type {} for format {}", number_type, format);
namespace Vulkan::LiverpoolToVK {
using DepthBuffer = Liverpool::DepthBuffer;
@ -725,55 +729,362 @@ void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) {
}
}
static constexpr float U8ToUnorm(u8 v) {
static constexpr auto c = 1.0f / 255.0f;
return float(v * c);
}
vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer) {
const auto comp_swap = color_buffer.info.comp_swap.Value();
ASSERT_MSG(comp_swap == Liverpool::ColorBuffer::SwapMode::Standard ||
comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate,
"Unsupported component swap mode {}", static_cast<u32>(comp_swap));
const bool comp_swap_alt = comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate;
const auto format = color_buffer.info.format.Value();
const auto number_type = color_buffer.info.number_type.Value();
const auto& c0 = color_buffer.clear_word0;
const auto& c1 = color_buffer.clear_word1;
const auto num_bits = AmdGpu::NumBits(color_buffer.info.format);
const auto num_components = AmdGpu::NumComponents(format);
const bool comp_swap_alt =
comp_swap == AmdGpu::Liverpool::ColorBuffer::SwapMode::Alternate ||
comp_swap == AmdGpu::Liverpool::ColorBuffer::SwapMode::AlternateReverse;
const bool comp_swap_reverse =
comp_swap == AmdGpu::Liverpool::ColorBuffer::SwapMode::StandardReverse ||
comp_swap == AmdGpu::Liverpool::ColorBuffer::SwapMode::AlternateReverse;
vk::ClearColorValue color{};
switch (color_buffer.info.number_type) {
case AmdGpu::NumberFormat::Snorm:
[[fallthrough]];
case AmdGpu::NumberFormat::SnormNz:
[[fallthrough]];
case AmdGpu::NumberFormat::Unorm:
[[fallthrough]];
case AmdGpu::NumberFormat::Srgb: {
switch (num_bits) {
case 32: {
color.float32 = std::array{
U8ToUnorm((c0 >> (comp_swap_alt ? 16 : 0)) & 0xff),
U8ToUnorm((c0 >> 8) & 0xff),
U8ToUnorm((c0 >> (comp_swap_alt ? 0 : 16)) & 0xff),
U8ToUnorm((c0 >> 24) & 0xff),
};
break;
}
default: {
LOG_ERROR(Render_Vulkan, "Missing clear color conversion for bits {}", num_bits);
break;
}
}
switch (number_type) {
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[3] = 1;
break;
default:
color.float32[3] = 1.0f;
break;
}
default: {
LOG_ERROR(Render_Vulkan, "Missing clear color conversion for type {}",
color_buffer.info.number_type.Value());
switch (format) {
case AmdGpu::DataFormat::Format8:
switch (number_type) {
case AmdGpu::NumberFormat::Unorm:
case AmdGpu::NumberFormat::Srgb: // Should we handle gamma correction here?
color.float32[0] = NumberUtils::U8ToUnorm(c0 & 0xff);
break;
break;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz:
color.float32[0] = NumberUtils::S8ToSnorm(c0 & 0xff);
break;
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0;
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format16:
switch (number_type) {
case AmdGpu::NumberFormat::Unorm:
color.float32[0] = NumberUtils::U16ToUnorm(c0 & 0xffff);
break;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz:
color.float32[0] = NumberUtils::S16ToSnorm(c0 & 0xffff);
break;
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0;
break;
case AmdGpu::NumberFormat::Float:
color.float32[0] = NumberUtils::Uf16ToF32(c0 & 0xffff);
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format8_8:
switch (number_type) {
case AmdGpu::NumberFormat::Unorm:
case AmdGpu::NumberFormat::Srgb: // Should we handle gamma correction here?
color.float32[0] = NumberUtils::U8ToUnorm(c0 & 0xff);
color.float32[1] = NumberUtils::U8ToUnorm((c0 >> 8) & 0xff);
break;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz:
color.float32[0] = NumberUtils::S8ToSnorm(c0 & 0xff);
color.float32[1] = NumberUtils::S8ToSnorm((c0 >> 8) & 0xff);
break;
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0 & 0xff;
color.uint32[1] = (c0 >> 8) & 0xff;
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format32:
switch (number_type) {
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0;
break;
case AmdGpu::NumberFormat::Float:
color.float32[0] = *(reinterpret_cast<const float*>(&c0));
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format16_16:
switch (number_type) {
case AmdGpu::NumberFormat::Unorm:
color.float32[0] = NumberUtils::U16ToUnorm(c0 & 0xffff);
color.float32[1] = NumberUtils::U16ToUnorm((c0 >> 16) & 0xffff);
break;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz:
color.float32[0] = NumberUtils::S16ToSnorm(c0 & 0xffff);
color.float32[1] = NumberUtils::S16ToSnorm((c0 >> 16) & 0xffff);
break;
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0 & 0xffff;
color.uint32[1] = (c0 >> 16) & 0xffff;
break;
case AmdGpu::NumberFormat::Float:
color.float32[0] = NumberUtils::Uf16ToF32(c0 & 0xffff);
color.float32[1] = NumberUtils::Uf16ToF32((c0 >> 16) & 0xffff);
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format10_11_11:
color.float32[0] = NumberUtils::Uf11ToF32(c0 & 0x7ff);
color.float32[1] = NumberUtils::Uf11ToF32((c0 >> 11) & 0x7ff);
color.float32[2] = NumberUtils::Uf10ToF32((c0 >> 22) & 0x3ff);
break;
case AmdGpu::DataFormat::Format11_11_10:
color.float32[0] = NumberUtils::Uf10ToF32(c0 & 0x3ff);
color.float32[1] = NumberUtils::Uf11ToF32((c0 >> 10) & 0x7ff);
color.float32[2] = NumberUtils::Uf11ToF32((c0 >> 21) & 0x7ff);
break;
case AmdGpu::DataFormat::Format5_9_9_9: {
int exponent;
union {
float f;
u32 u;
} scale;
exponent = (c0 >> 27) - 10;
scale.u = (exponent + 127) << 23;
color.float32[0] = (c0 & 0x1ff) * scale.f;
color.float32[1] = ((c0 >> 9) & 0x1ff) * scale.f;
color.float32[2] = ((c0 >> 18) & 0x1ff) * scale.f;
break;
}
case AmdGpu::DataFormat::Format10_10_10_2:
switch (number_type) {
case AmdGpu::NumberFormat::Unorm:
color.float32[0] = NumberUtils::U2ToUnorm(c0 & 0x3);
color.float32[1] = NumberUtils::U10ToUnorm((c0 >> 2) & 0x3ff);
color.float32[2] = NumberUtils::U10ToUnorm((c0 >> 12) & 0x3ff);
color.float32[3] = NumberUtils::U10ToUnorm(c0 >> 22);
break;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz:
color.float32[0] = NumberUtils::S2ToSnorm(c0 & 0x3);
color.float32[1] = NumberUtils::S10ToSnorm((c0 >> 2) & 0x3ff);
color.float32[2] = NumberUtils::S10ToSnorm((c0 >> 12) & 0x3ff);
color.float32[3] = NumberUtils::S2ToSnorm(c0 >> 22);
break;
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0 & 0x3;
color.uint32[1] = (c0 >> 2) & 0x3ff;
color.uint32[2] = (c0 >> 12) & 0x3ff;
color.uint32[3] = c0 >> 22;
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format2_10_10_10:
switch (number_type) {
case AmdGpu::NumberFormat::Unorm:
color.float32[0] = NumberUtils::U10ToUnorm(c0 & 0x3ff);
color.float32[1] = NumberUtils::U10ToUnorm((c0 >> 10) & 0x3ff);
color.float32[2] = NumberUtils::U10ToUnorm((c0 >> 20) & 0x3ff);
color.float32[3] = NumberUtils::U2ToUnorm(c0 >> 30);
break;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz:
color.float32[0] = NumberUtils::S10ToSnorm(c0 & 0x3ff);
color.float32[1] = NumberUtils::S10ToSnorm((c0 >> 10) & 0x3ff);
color.float32[2] = NumberUtils::S10ToSnorm((c0 >> 20) & 0x3ff);
color.float32[3] = NumberUtils::S2ToSnorm(c0 >> 30);
break;
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0 & 0x3ff;
color.uint32[1] = (c0 >> 10) & 0x3ff;
color.uint32[2] = (c0 >> 20) & 0x3ff;
color.uint32[3] = c0 >> 30;
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format8_8_8_8:
switch (number_type) {
case AmdGpu::NumberFormat::Unorm:
case AmdGpu::NumberFormat::Srgb: // Should we handle gamma correction here?
color.float32[0] = NumberUtils::U8ToUnorm(c0 & 0xff);
color.float32[1] = NumberUtils::U8ToUnorm((c0 >> 8) & 0xff);
color.float32[2] = NumberUtils::U8ToUnorm((c0 >> 16) & 0xff);
color.float32[3] = NumberUtils::U8ToUnorm(c0 >> 24);
break;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz:
color.float32[0] = NumberUtils::S8ToSnorm(c0 & 0xff);
color.float32[1] = NumberUtils::S8ToSnorm((c0 >> 8) & 0xff);
color.float32[2] = NumberUtils::S8ToSnorm((c0 >> 16) & 0xff);
color.float32[3] = NumberUtils::S8ToSnorm(c0 >> 24);
break;
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0 & 0xff;
color.uint32[1] = (c0 >> 8) & 0xff;
color.uint32[2] = (c0 >> 16) & 0xff;
color.uint32[3] = c0 >> 24;
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format32_32:
switch (number_type) {
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0;
color.uint32[1] = c1;
break;
case AmdGpu::NumberFormat::Float:
color.float32[0] = *(reinterpret_cast<const float*>(&c0));
color.float32[1] = *(reinterpret_cast<const float*>(&c1));
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format16_16_16_16:
switch (number_type) {
case AmdGpu::NumberFormat::Unorm:
color.float32[0] = NumberUtils::U16ToUnorm(c0 & 0xffff);
color.float32[1] = NumberUtils::U16ToUnorm((c0 >> 16) & 0xffff);
color.float32[2] = NumberUtils::U16ToUnorm(c1 & 0xffff);
color.float32[3] = NumberUtils::U16ToUnorm((c1 >> 16) & 0xffff);
break;
case AmdGpu::NumberFormat::Snorm:
case AmdGpu::NumberFormat::SnormNz:
color.float32[0] = NumberUtils::S16ToSnorm(c0 & 0xffff);
color.float32[1] = NumberUtils::S16ToSnorm((c0 >> 16) & 0xffff);
color.float32[2] = NumberUtils::S16ToSnorm(c1 & 0xffff);
color.float32[3] = NumberUtils::S16ToSnorm((c1 >> 16) & 0xffff);
break;
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0 & 0xffff;
color.uint32[1] = (c0 >> 16) & 0xffff;
color.uint32[2] = c1 & 0xffff;
color.uint32[3] = (c1 >> 16) & 0xffff;
break;
case AmdGpu::NumberFormat::Float:
color.float32[0] = NumberUtils::Uf16ToF32(c0 & 0xffff);
color.float32[1] = NumberUtils::Uf16ToF32((c0 >> 16) & 0xffff);
color.float32[2] = NumberUtils::Uf16ToF32(c1 & 0xffff);
color.float32[3] = NumberUtils::Uf16ToF32((c1 >> 16) & 0xffff);
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format32_32_32_32:
switch (number_type) {
case AmdGpu::NumberFormat::Uint:
case AmdGpu::NumberFormat::Sint:
color.uint32[0] = c0;
color.uint32[1] = c0;
color.uint32[2] = c0;
color.uint32[3] = c1;
break;
case AmdGpu::NumberFormat::Float:
color.float32[0] = *(reinterpret_cast<const float*>(&c0));
color.float32[1] = *(reinterpret_cast<const float*>(&c0));
color.float32[2] = *(reinterpret_cast<const float*>(&c0));
color.float32[3] = *(reinterpret_cast<const float*>(&c1));
break;
default:
INVALID_NUMBER_FORMAT_COMBO;
break;
}
break;
case AmdGpu::DataFormat::Format5_6_5:
color.float32[0] = NumberUtils::U5ToUnorm(c0 & 0x1f);
color.float32[1] = NumberUtils::U6ToUnorm((c0 >> 5) & 0x3f);
color.float32[2] = NumberUtils::U5ToUnorm(c0 >> 11);
break;
case AmdGpu::DataFormat::Format1_5_5_5:
color.float32[0] = NumberUtils::U5ToUnorm(c0 & 0x1f);
color.float32[1] = NumberUtils::U5ToUnorm((c0 >> 5) & 0x1f);
color.float32[2] = NumberUtils::U5ToUnorm((c0 >> 10) & 0x1f);
color.float32[3] = (c0 >> 15) ? 1.0f : 0.0f;
break;
case AmdGpu::DataFormat::Format5_5_5_1:
color.float32[0] = (c0 & 0x1) ? 1.0f : 0.0f;
color.float32[1] = NumberUtils::U5ToUnorm((c0 >> 1) & 0x1f);
color.float32[2] = NumberUtils::U5ToUnorm((c0 >> 6) & 0x1f);
color.float32[3] = NumberUtils::U5ToUnorm((c0 >> 11) & 0x1f);
break;
case AmdGpu::DataFormat::Format4_4_4_4:
color.float32[0] = NumberUtils::U4ToUnorm(c0 & 0xf);
color.float32[1] = NumberUtils::U4ToUnorm((c0 >> 4) & 0xf);
color.float32[2] = NumberUtils::U4ToUnorm((c0 >> 8) & 0xf);
color.float32[3] = NumberUtils::U4ToUnorm(c0 >> 12);
break;
default:
LOG_ERROR(Render_Vulkan, "Unsupported color buffer format: {}", format);
break;
}
if (num_components == 1) {
if (comp_swap != Liverpool::ColorBuffer::SwapMode::Standard) {
color.float32[static_cast<int>(comp_swap)] = color.float32[0];
color.float32[0] = 0.0f;
}
} else {
if (comp_swap_alt && num_components == 4) {
std::swap(color.float32[0], color.float32[2]);
}
if (comp_swap_reverse) {
std::reverse(std::begin(color.float32), std::begin(color.float32) + num_components);
}
if (comp_swap_alt && num_components != 4) {
color.float32[3] = color.float32[num_components - 1];
color.float32[num_components - 1] = 0.0f;
}
}
return {.color = color};
}