Fermi2D: Implement Bilinear software filtering and address feedback.
This commit is contained in:
parent
957840be91
commit
5fbd6954ef
|
@ -62,11 +62,15 @@ void Fermi2D::Blit() {
|
||||||
|
|
||||||
const auto& args = regs.pixels_from_memory;
|
const auto& args = regs.pixels_from_memory;
|
||||||
constexpr s64 null_derivate = 1ULL << 32;
|
constexpr s64 null_derivate = 1ULL << 32;
|
||||||
|
Surface src = regs.src;
|
||||||
|
const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format));
|
||||||
|
const bool delegate_to_gpu = src.width > 512 && src.height > 512 && bytes_per_pixel <= 8 &&
|
||||||
|
src.format != regs.dst.format;
|
||||||
Config config{
|
Config config{
|
||||||
.operation = regs.operation,
|
.operation = regs.operation,
|
||||||
.filter = args.sample_mode.filter,
|
.filter = args.sample_mode.filter,
|
||||||
.must_accelerate = args.du_dx != null_derivate || args.dv_dy != null_derivate ||
|
.must_accelerate =
|
||||||
args.sample_mode.filter == Filter::Bilinear,
|
args.du_dx != null_derivate || args.dv_dy != null_derivate || delegate_to_gpu,
|
||||||
.dst_x0 = args.dst_x0,
|
.dst_x0 = args.dst_x0,
|
||||||
.dst_y0 = args.dst_y0,
|
.dst_y0 = args.dst_y0,
|
||||||
.dst_x1 = args.dst_x0 + args.dst_width,
|
.dst_x1 = args.dst_x0 + args.dst_width,
|
||||||
|
@ -76,8 +80,7 @@ void Fermi2D::Blit() {
|
||||||
.src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32),
|
.src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32),
|
||||||
.src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32),
|
.src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32),
|
||||||
};
|
};
|
||||||
Surface src = regs.src;
|
|
||||||
const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format));
|
|
||||||
const auto need_align_to_pitch =
|
const auto need_align_to_pitch =
|
||||||
src.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch &&
|
src.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch &&
|
||||||
static_cast<s32>(src.width) == config.src_x1 &&
|
static_cast<s32>(src.width) == config.src_x1 &&
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "video_core/engines/sw_blitter/blitter.h"
|
#include "video_core/engines/sw_blitter/blitter.h"
|
||||||
|
@ -22,8 +24,10 @@ using namespace Texture;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void NeighrestNeighbor(std::span<u8> input, std::span<u8> output, u32 src_width, u32 src_height,
|
constexpr size_t ir_components = 4;
|
||||||
u32 dst_width, u32 dst_height, size_t bpp) {
|
|
||||||
|
void NeighrestNeighbor(std::span<const u8> input, std::span<u8> output, u32 src_width,
|
||||||
|
u32 src_height, u32 dst_width, u32 dst_height, size_t bpp) {
|
||||||
const size_t dx_du = std::llround((static_cast<f64>(src_width) / dst_width) * (1ULL << 32));
|
const size_t dx_du = std::llround((static_cast<f64>(src_width) / dst_width) * (1ULL << 32));
|
||||||
const size_t dy_dv = std::llround((static_cast<f64>(src_height) / dst_height) * (1ULL << 32));
|
const size_t dy_dv = std::llround((static_cast<f64>(src_height) / dst_height) * (1ULL << 32));
|
||||||
size_t src_y = 0;
|
size_t src_y = 0;
|
||||||
|
@ -40,7 +44,7 @@ void NeighrestNeighbor(std::span<u8> input, std::span<u8> output, u32 src_width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NeighrestNeighborFast(std::span<f32> input, std::span<f32> output, u32 src_width,
|
void NeighrestNeighborFast(std::span<const f32> input, std::span<f32> output, u32 src_width,
|
||||||
u32 src_height, u32 dst_width, u32 dst_height) {
|
u32 src_height, u32 dst_width, u32 dst_height) {
|
||||||
const size_t dx_du = std::llround((static_cast<f64>(src_width) / dst_width) * (1ULL << 32));
|
const size_t dx_du = std::llround((static_cast<f64>(src_width) / dst_width) * (1ULL << 32));
|
||||||
const size_t dy_dv = std::llround((static_cast<f64>(src_height) / dst_height) * (1ULL << 32));
|
const size_t dy_dv = std::llround((static_cast<f64>(src_height) / dst_height) * (1ULL << 32));
|
||||||
|
@ -48,44 +52,62 @@ void NeighrestNeighborFast(std::span<f32> input, std::span<f32> output, u32 src_
|
||||||
for (u32 y = 0; y < dst_height; y++) {
|
for (u32 y = 0; y < dst_height; y++) {
|
||||||
size_t src_x = 0;
|
size_t src_x = 0;
|
||||||
for (u32 x = 0; x < dst_width; x++) {
|
for (u32 x = 0; x < dst_width; x++) {
|
||||||
const size_t read_from = ((src_y * src_width + src_x) >> 32) * 4;
|
const size_t read_from = ((src_y * src_width + src_x) >> 32) * ir_components;
|
||||||
const size_t write_to = (y * dst_width + x) * 4;
|
const size_t write_to = (y * dst_width + x) * ir_components;
|
||||||
|
|
||||||
std::memcpy(&output[write_to], &input[read_from], sizeof(f32) * 4);
|
std::memcpy(&output[write_to], &input[read_from], sizeof(f32) * ir_components);
|
||||||
src_x += dx_du;
|
src_x += dx_du;
|
||||||
}
|
}
|
||||||
src_y += dy_dv;
|
src_y += dy_dv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void Bilinear(std::span<const f32> input, std::span<f32> output, size_t src_width,
|
||||||
void Bilinear(std::span<f32> input, std::span<f32> output, size_t src_width,
|
|
||||||
size_t src_height, size_t dst_width, size_t dst_height) {
|
size_t src_height, size_t dst_width, size_t dst_height) {
|
||||||
const auto inv_lerp = [](u32 coord, u32 end) { return
|
const auto bilinear_sample = [](std::span<const f32> x0_y0, std::span<const f32> x1_y0,
|
||||||
static_cast<f32>(std::min(std::max(static_cast<s32>(coord), 0), end - 1)) / (end); };
|
std::span<const f32> x0_y1, std::span<const f32> x1_y1,
|
||||||
|
f32 weight_x, f32 weight_y) {
|
||||||
|
std::array<f32, ir_components> result{};
|
||||||
for (u32 y = 0; y < dst_height; y++) {
|
for (size_t i = 0; i < ir_components; i++) {
|
||||||
const f32 ty_0 = inv_lerp(y, dst_extent_y);
|
const f32 a = std::lerp(x0_y0[i], x1_y0[i], weight_x);
|
||||||
const f32 ty_1 = inv_lerp(y + 1, dst_extent_y);
|
const f32 b = std::lerp(x0_y1[i], x1_y1[i], weight_x);
|
||||||
for (u32 x = 0; x < dst_width; x++) {
|
result[i] = std::lerp(a, b, weight_y);
|
||||||
const f32 tx_0 = inv_lerp(x, dst_extent_x);
|
}
|
||||||
const f32 tx_1 = inv_lerp(x + 1, dst_extent_x);
|
return result;
|
||||||
const std::array<f32, 4> get_pixel = [&](f32 tx, f32 ty, u32 width, u32 height) {
|
|
||||||
std::array<f32, 4> result{};
|
|
||||||
|
|
||||||
return (std::llround(width * tx) + std::llround(height * ty) * width) * 4;
|
|
||||||
};
|
};
|
||||||
std::array<f32, 4> result{};
|
const f32 dx_du =
|
||||||
|
dst_width > 1 ? static_cast<f32>(src_width - 1) / static_cast<f32>(dst_width - 1) : 0.f;
|
||||||
|
const f32 dy_dv =
|
||||||
|
dst_height > 1 ? static_cast<f32>(src_height - 1) / static_cast<f32>(dst_height - 1) : 0.f;
|
||||||
|
for (u32 y = 0; y < dst_height; y++) {
|
||||||
|
for (u32 x = 0; x < dst_width; x++) {
|
||||||
|
const f32 x_low = std::floor(static_cast<f32>(x) * dx_du);
|
||||||
|
const f32 y_low = std::floor(static_cast<f32>(y) * dy_dv);
|
||||||
|
const f32 x_high = std::ceil(static_cast<f32>(x) * dx_du);
|
||||||
|
const f32 y_high = std::ceil(static_cast<f32>(y) * dy_dv);
|
||||||
|
const f32 weight_x = (static_cast<f32>(x) * dx_du) - x_low;
|
||||||
|
const f32 weight_y = (static_cast<f32>(y) * dy_dv) - y_low;
|
||||||
|
|
||||||
const size_t read_from = get_pixel(src_width, src_height);
|
const auto read_src = [&](f32 in_x, f32 in_y) {
|
||||||
const size_t write_to = get_pixel(tx_0, ty_0, dst_width, dst_height);
|
const size_t read_from =
|
||||||
|
((static_cast<size_t>(in_x) * src_width + static_cast<size_t>(in_y)) >> 32) *
|
||||||
|
ir_components;
|
||||||
|
return std::span<const f32>(&input[read_from], ir_components);
|
||||||
|
};
|
||||||
|
|
||||||
std::memcpy(&output[write_to], &input[read_from], bpp);
|
auto x0_y0 = read_src(x_low, y_low);
|
||||||
|
auto x1_y0 = read_src(x_high, y_low);
|
||||||
|
auto x0_y1 = read_src(x_low, y_high);
|
||||||
|
auto x1_y1 = read_src(x_high, y_high);
|
||||||
|
|
||||||
|
const auto result = bilinear_sample(x0_y0, x1_y0, x0_y1, x1_y1, weight_x, weight_y);
|
||||||
|
|
||||||
|
const size_t write_to = (y * dst_width + x) * ir_components;
|
||||||
|
|
||||||
|
std::memcpy(&output[write_to], &result, sizeof(f32) * ir_components);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -107,8 +129,6 @@ SoftwareBlitEngine::~SoftwareBlitEngine() = default;
|
||||||
|
|
||||||
bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
|
bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
|
||||||
Fermi2D::Config& config) {
|
Fermi2D::Config& config) {
|
||||||
UNIMPLEMENTED_IF(config.filter == Fermi2D::Filter::Bilinear);
|
|
||||||
|
|
||||||
const auto get_surface_size = [](Fermi2D::Surface& surface, u32 bytes_per_pixel) {
|
const auto get_surface_size = [](Fermi2D::Surface& surface, u32 bytes_per_pixel) {
|
||||||
if (surface.linear == Fermi2D::MemoryLayout::BlockLinear) {
|
if (surface.linear == Fermi2D::MemoryLayout::BlockLinear) {
|
||||||
return CalculateSize(true, bytes_per_pixel, surface.width, surface.height,
|
return CalculateSize(true, bytes_per_pixel, surface.width, surface.height,
|
||||||
|
@ -116,9 +136,9 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
|
||||||
}
|
}
|
||||||
return static_cast<size_t>(surface.pitch * surface.height);
|
return static_cast<size_t>(surface.pitch * surface.height);
|
||||||
};
|
};
|
||||||
const auto process_pitch_linear = [](bool unpack, std::span<u8> input, std::span<u8> output,
|
const auto process_pitch_linear = [](bool unpack, std::span<const u8> input,
|
||||||
u32 extent_x, u32 extent_y, u32 pitch, u32 x0, u32 y0,
|
std::span<u8> output, u32 extent_x, u32 extent_y,
|
||||||
size_t bpp) {
|
u32 pitch, u32 x0, u32 y0, size_t bpp) {
|
||||||
const size_t base_offset = x0 * bpp;
|
const size_t base_offset = x0 * bpp;
|
||||||
const size_t copy_size = extent_x * bpp;
|
const size_t copy_size = extent_x * bpp;
|
||||||
for (u32 y = y0; y < extent_y; y++) {
|
for (u32 y = y0; y < extent_y; y++) {
|
||||||
|
@ -157,12 +177,17 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
|
||||||
|
|
||||||
const auto convertion_phase_ir = [&]() {
|
const auto convertion_phase_ir = [&]() {
|
||||||
auto* input_converter = impl->converter_factory.GetFormatConverter(src.format);
|
auto* input_converter = impl->converter_factory.GetFormatConverter(src.format);
|
||||||
impl->intermediate_src.resize((src_copy_size / src_bytes_per_pixel) * 4);
|
impl->intermediate_src.resize((src_copy_size / src_bytes_per_pixel) * ir_components);
|
||||||
impl->intermediate_dst.resize((dst_copy_size / dst_bytes_per_pixel) * 4);
|
impl->intermediate_dst.resize((dst_copy_size / dst_bytes_per_pixel) * ir_components);
|
||||||
input_converter->ConvertTo(impl->src_buffer, impl->intermediate_src);
|
input_converter->ConvertTo(impl->src_buffer, impl->intermediate_src);
|
||||||
|
|
||||||
|
if (config.filter != Fermi2D::Filter::Bilinear) {
|
||||||
NeighrestNeighborFast(impl->intermediate_src, impl->intermediate_dst, src_extent_x,
|
NeighrestNeighborFast(impl->intermediate_src, impl->intermediate_dst, src_extent_x,
|
||||||
src_extent_y, dst_extent_x, dst_extent_y);
|
src_extent_y, dst_extent_x, dst_extent_y);
|
||||||
|
} else {
|
||||||
|
Bilinear(impl->intermediate_src, impl->intermediate_dst, src_extent_x, src_extent_y,
|
||||||
|
dst_extent_x, dst_extent_y);
|
||||||
|
}
|
||||||
|
|
||||||
auto* output_converter = impl->converter_factory.GetFormatConverter(dst.format);
|
auto* output_converter = impl->converter_factory.GetFormatConverter(dst.format);
|
||||||
output_converter->ConvertFrom(impl->intermediate_dst, impl->dst_buffer);
|
output_converter->ConvertFrom(impl->intermediate_dst, impl->dst_buffer);
|
||||||
|
@ -183,7 +208,7 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
|
||||||
|
|
||||||
// Conversion Phase
|
// Conversion Phase
|
||||||
if (no_passthrough) {
|
if (no_passthrough) {
|
||||||
if (src.format != dst.format) {
|
if (src.format != dst.format || config.filter == Fermi2D::Filter::Bilinear) {
|
||||||
convertion_phase_ir();
|
convertion_phase_ir();
|
||||||
} else {
|
} else {
|
||||||
convertion_phase_same_format();
|
convertion_phase_same_format();
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Tegra::Engines::Blitter {
|
||||||
|
|
||||||
class SoftwareBlitEngine {
|
class SoftwareBlitEngine {
|
||||||
public:
|
public:
|
||||||
SoftwareBlitEngine(MemoryManager& memory_manager_);
|
explicit SoftwareBlitEngine(MemoryManager& memory_manager_);
|
||||||
~SoftwareBlitEngine();
|
~SoftwareBlitEngine();
|
||||||
|
|
||||||
bool Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst, Fermi2D::Config& copy_config);
|
bool Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst, Fermi2D::Config& copy_config);
|
||||||
|
|
|
@ -139,7 +139,7 @@ struct R32B32G32A32_FLOATTraits {
|
||||||
ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
|
ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
|
static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::A, Swizzle::G, Swizzle::B, Swizzle::R};
|
Swizzle::R, Swizzle::B, Swizzle::G, Swizzle::A};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R32G32B32A32_SINTTraits {
|
struct R32G32B32A32_SINTTraits {
|
||||||
|
@ -148,7 +148,7 @@ struct R32G32B32A32_SINTTraits {
|
||||||
ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
|
ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
|
static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R32G32B32A32_UINTTraits {
|
struct R32G32B32A32_UINTTraits {
|
||||||
|
@ -157,7 +157,7 @@ struct R32G32B32A32_UINTTraits {
|
||||||
ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
|
ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
|
static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16B16A16_UNORMTraits {
|
struct R16G16B16A16_UNORMTraits {
|
||||||
|
@ -166,7 +166,7 @@ struct R16G16B16A16_UNORMTraits {
|
||||||
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16B16A16_SNORMTraits {
|
struct R16G16B16A16_SNORMTraits {
|
||||||
|
@ -175,7 +175,7 @@ struct R16G16B16A16_SNORMTraits {
|
||||||
ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM};
|
ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16B16A16_SINTTraits {
|
struct R16G16B16A16_SINTTraits {
|
||||||
|
@ -184,7 +184,7 @@ struct R16G16B16A16_SINTTraits {
|
||||||
ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
|
ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16B16A16_UINTTraits {
|
struct R16G16B16A16_UINTTraits {
|
||||||
|
@ -193,7 +193,7 @@ struct R16G16B16A16_UINTTraits {
|
||||||
ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
|
ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16B16A16_FLOATTraits {
|
struct R16G16B16A16_FLOATTraits {
|
||||||
|
@ -202,7 +202,7 @@ struct R16G16B16A16_FLOATTraits {
|
||||||
ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
|
ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R32G32_FLOATTraits {
|
struct R32G32_FLOATTraits {
|
||||||
|
@ -210,8 +210,8 @@ struct R32G32_FLOATTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::FLOAT, ComponentType::FLOAT};
|
ComponentType::FLOAT, ComponentType::FLOAT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
|
static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R32G32_SINTTraits {
|
struct R32G32_SINTTraits {
|
||||||
|
@ -219,8 +219,8 @@ struct R32G32_SINTTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::SINT, ComponentType::SINT};
|
ComponentType::SINT, ComponentType::SINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
|
static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R32G32_UINTTraits {
|
struct R32G32_UINTTraits {
|
||||||
|
@ -228,8 +228,8 @@ struct R32G32_UINTTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UINT, ComponentType::UINT};
|
ComponentType::UINT, ComponentType::UINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
|
static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16B16X16_FLOATTraits {
|
struct R16G16B16X16_FLOATTraits {
|
||||||
|
@ -238,7 +238,7 @@ struct R16G16B16X16_FLOATTraits {
|
||||||
ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
|
ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::None, Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::None};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A8R8G8B8_UNORMTraits {
|
struct A8R8G8B8_UNORMTraits {
|
||||||
|
@ -247,7 +247,7 @@ struct A8R8G8B8_UNORMTraits {
|
||||||
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::B, Swizzle::G, Swizzle::R, Swizzle::A};
|
Swizzle::A, Swizzle::R, Swizzle::G, Swizzle::B};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A8R8G8B8_SRGBTraits {
|
struct A8R8G8B8_SRGBTraits {
|
||||||
|
@ -256,25 +256,25 @@ struct A8R8G8B8_SRGBTraits {
|
||||||
ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB};
|
ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::B, Swizzle::G, Swizzle::R, Swizzle::A};
|
Swizzle::A, Swizzle::R, Swizzle::G, Swizzle::B};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A2B10G10R10_UNORMTraits {
|
struct A2B10G10R10_UNORMTraits {
|
||||||
static constexpr size_t num_components = 4;
|
static constexpr size_t num_components = 4;
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {10, 10, 10, 2};
|
static constexpr std::array<size_t, num_components> component_sizes = {2, 10, 10, 10};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A2B10G10R10_UINTTraits {
|
struct A2B10G10R10_UINTTraits {
|
||||||
static constexpr size_t num_components = 4;
|
static constexpr size_t num_components = 4;
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
|
ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {10, 10, 10, 2};
|
static constexpr std::array<size_t, num_components> component_sizes = {2, 10, 10, 10};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A8B8G8R8_UNORMTraits {
|
struct A8B8G8R8_UNORMTraits {
|
||||||
|
@ -283,7 +283,7 @@ struct A8B8G8R8_UNORMTraits {
|
||||||
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A8B8G8R8_SRGBTraits {
|
struct A8B8G8R8_SRGBTraits {
|
||||||
|
@ -292,7 +292,7 @@ struct A8B8G8R8_SRGBTraits {
|
||||||
ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB};
|
ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A8B8G8R8_SNORMTraits {
|
struct A8B8G8R8_SNORMTraits {
|
||||||
|
@ -301,7 +301,7 @@ struct A8B8G8R8_SNORMTraits {
|
||||||
ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM};
|
ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A8B8G8R8_SINTTraits {
|
struct A8B8G8R8_SINTTraits {
|
||||||
|
@ -310,7 +310,7 @@ struct A8B8G8R8_SINTTraits {
|
||||||
ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
|
ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A8B8G8R8_UINTTraits {
|
struct A8B8G8R8_UINTTraits {
|
||||||
|
@ -319,7 +319,7 @@ struct A8B8G8R8_UINTTraits {
|
||||||
ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
|
ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
|
Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16_UNORMTraits {
|
struct R16G16_UNORMTraits {
|
||||||
|
@ -327,8 +327,8 @@ struct R16G16_UNORMTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UNORM, ComponentType::UNORM};
|
ComponentType::UNORM, ComponentType::UNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16_SNORMTraits {
|
struct R16G16_SNORMTraits {
|
||||||
|
@ -336,8 +336,8 @@ struct R16G16_SNORMTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::SNORM, ComponentType::SNORM};
|
ComponentType::SNORM, ComponentType::SNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16_SINTTraits {
|
struct R16G16_SINTTraits {
|
||||||
|
@ -345,8 +345,8 @@ struct R16G16_SINTTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::SINT, ComponentType::SINT};
|
ComponentType::SINT, ComponentType::SINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16_UINTTraits {
|
struct R16G16_UINTTraits {
|
||||||
|
@ -354,8 +354,8 @@ struct R16G16_UINTTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UINT, ComponentType::UINT};
|
ComponentType::UINT, ComponentType::UINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16G16_FLOATTraits {
|
struct R16G16_FLOATTraits {
|
||||||
|
@ -363,17 +363,17 @@ struct R16G16_FLOATTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::FLOAT, ComponentType::FLOAT};
|
ComponentType::FLOAT, ComponentType::FLOAT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct B10G11R11_FLOATTraits {
|
struct B10G11R11_FLOATTraits {
|
||||||
static constexpr size_t num_components = 3;
|
static constexpr size_t num_components = 3;
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
|
ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {11, 11, 10};
|
static constexpr std::array<size_t, num_components> component_sizes = {10, 11, 11};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::R, Swizzle::G, Swizzle::B};
|
Swizzle::B, Swizzle::G, Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R32_SINTTraits {
|
struct R32_SINTTraits {
|
||||||
|
@ -400,22 +400,40 @@ struct R32_FLOATTraits {
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R};
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct X8R8G8B8_UNORMTraits {
|
||||||
|
static constexpr size_t num_components = 4;
|
||||||
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
|
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
||||||
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
|
Swizzle::None, Swizzle::R, Swizzle::G, Swizzle::B};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X8R8G8B8_SRGBTraits {
|
||||||
|
static constexpr size_t num_components = 4;
|
||||||
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
|
ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB};
|
||||||
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
|
||||||
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
|
Swizzle::None, Swizzle::R, Swizzle::G, Swizzle::B};
|
||||||
|
};
|
||||||
|
|
||||||
struct R5G6B5_UNORMTraits {
|
struct R5G6B5_UNORMTraits {
|
||||||
static constexpr size_t num_components = 3;
|
static constexpr size_t num_components = 3;
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {5, 6, 5};
|
static constexpr std::array<size_t, num_components> component_sizes = {5, 6, 5};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::B, Swizzle::G, Swizzle::R};
|
Swizzle::R, Swizzle::G, Swizzle::B};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct A1R5G5B5_UNORMTraits {
|
struct A1R5G5B5_UNORMTraits {
|
||||||
static constexpr size_t num_components = 4;
|
static constexpr size_t num_components = 4;
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {5, 5, 5, 1};
|
static constexpr std::array<size_t, num_components> component_sizes = {1, 5, 5, 5};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {
|
||||||
Swizzle::B, Swizzle::G, Swizzle::R, Swizzle::A};
|
Swizzle::A, Swizzle::R, Swizzle::G, Swizzle::B};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R8G8_UNORMTraits {
|
struct R8G8_UNORMTraits {
|
||||||
|
@ -423,8 +441,8 @@ struct R8G8_UNORMTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UNORM, ComponentType::UNORM};
|
ComponentType::UNORM, ComponentType::UNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R8G8_SNORMTraits {
|
struct R8G8_SNORMTraits {
|
||||||
|
@ -432,8 +450,8 @@ struct R8G8_SNORMTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::SNORM, ComponentType::SNORM};
|
ComponentType::SNORM, ComponentType::SNORM};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R8G8_SINTTraits {
|
struct R8G8_SINTTraits {
|
||||||
|
@ -441,8 +459,8 @@ struct R8G8_SINTTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::SINT, ComponentType::SINT};
|
ComponentType::SINT, ComponentType::SINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R8G8_UINTTraits {
|
struct R8G8_UINTTraits {
|
||||||
|
@ -450,8 +468,8 @@ struct R8G8_UINTTraits {
|
||||||
static constexpr std::array<ComponentType, num_components> component_types = {
|
static constexpr std::array<ComponentType, num_components> component_types = {
|
||||||
ComponentType::UINT, ComponentType::UINT};
|
ComponentType::UINT, ComponentType::UINT};
|
||||||
static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
|
static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
|
||||||
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G,
|
static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
|
||||||
Swizzle::R};
|
Swizzle::G};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct R16_UNORMTraits {
|
struct R16_UNORMTraits {
|
||||||
|
@ -611,7 +629,7 @@ private:
|
||||||
constexpr size_t fp16_mantissa_bits = 10;
|
constexpr size_t fp16_mantissa_bits = 10;
|
||||||
constexpr size_t mantissa_mask =
|
constexpr size_t mantissa_mask =
|
||||||
~((1ULL << (fp32_mantissa_bits - fp16_mantissa_bits)) - 1ULL);
|
~((1ULL << (fp32_mantissa_bits - fp16_mantissa_bits)) - 1ULL);
|
||||||
tmp = tmp & mantissa_mask;
|
tmp = tmp & static_cast<u32>(mantissa_mask);
|
||||||
// TODO: force the exponent within the range of half float. Not needed in UNORM / SNORM
|
// TODO: force the exponent within the range of half float. Not needed in UNORM / SNORM
|
||||||
return std::bit_cast<f32>(tmp);
|
return std::bit_cast<f32>(tmp);
|
||||||
};
|
};
|
||||||
|
@ -624,12 +642,13 @@ private:
|
||||||
};
|
};
|
||||||
const auto calculate_snorm = [&]() {
|
const auto calculate_snorm = [&]() {
|
||||||
return static_cast<f32>(
|
return static_cast<f32>(
|
||||||
static_cast<f64>(sign_extend(value, component_sizes[which_component])) /
|
static_cast<f32>(sign_extend(value, component_sizes[which_component])) /
|
||||||
((1ULL << (component_sizes[which_component] - 1ULL)) - 1ULL));
|
static_cast<f32>((1ULL << (component_sizes[which_component] - 1ULL)) - 1ULL));
|
||||||
};
|
};
|
||||||
const auto calculate_unorm = [&]() {
|
const auto calculate_unorm = [&]() {
|
||||||
return static_cast<f32>(static_cast<f32>(value) /
|
return static_cast<f32>(
|
||||||
((1ULL << (component_sizes[which_component])) - 1ULL));
|
static_cast<f32>(value) /
|
||||||
|
static_cast<f32>((1ULL << (component_sizes[which_component])) - 1ULL));
|
||||||
};
|
};
|
||||||
if constexpr (component_types[which_component] == ComponentType::SNORM) {
|
if constexpr (component_types[which_component] == ComponentType::SNORM) {
|
||||||
out_component = calculate_snorm();
|
out_component = calculate_snorm();
|
||||||
|
@ -688,14 +707,15 @@ private:
|
||||||
return tmp_value >> shift_towards;
|
return tmp_value >> shift_towards;
|
||||||
};
|
};
|
||||||
const auto calculate_unorm = [&]() {
|
const auto calculate_unorm = [&]() {
|
||||||
return static_cast<u32>(static_cast<f32>(in_component) *
|
return static_cast<u32>(
|
||||||
((1ULL << (component_sizes[which_component])) - 1ULL));
|
static_cast<f32>(in_component) *
|
||||||
|
static_cast<f32>((1ULL << (component_sizes[which_component])) - 1ULL));
|
||||||
};
|
};
|
||||||
if constexpr (component_types[which_component] == ComponentType::SNORM ||
|
if constexpr (component_types[which_component] == ComponentType::SNORM ||
|
||||||
component_types[which_component] == ComponentType::SNORM_FORCE_FP16) {
|
component_types[which_component] == ComponentType::SNORM_FORCE_FP16) {
|
||||||
s32 tmp_word =
|
s32 tmp_word = static_cast<s32>(
|
||||||
static_cast<s32>(static_cast<f64>(in_component) *
|
static_cast<f32>(in_component) *
|
||||||
((1ULL << (component_sizes[which_component] - 1ULL)) - 1ULL));
|
static_cast<f32>((1ULL << (component_sizes[which_component] - 1ULL)) - 1ULL));
|
||||||
insert_to_word(tmp_word);
|
insert_to_word(tmp_word);
|
||||||
|
|
||||||
} else if constexpr (component_types[which_component] == ComponentType::UNORM ||
|
} else if constexpr (component_types[which_component] == ComponentType::UNORM ||
|
||||||
|
@ -714,11 +734,12 @@ private:
|
||||||
insert_to_word(tmp_word);
|
insert_to_word(tmp_word);
|
||||||
} else if constexpr (component_sizes[which_component] == 16) {
|
} else if constexpr (component_sizes[which_component] == 16) {
|
||||||
static constexpr u32 sign_mask = 0x8000;
|
static constexpr u32 sign_mask = 0x8000;
|
||||||
static constexpr u32 mantissa_mask = 0x8000;
|
static constexpr u32 mantissa_mask = 0x03ff;
|
||||||
|
static constexpr u32 exponent_mask = 0x7c00;
|
||||||
const u32 tmp_word = std::bit_cast<u32>(in_component);
|
const u32 tmp_word = std::bit_cast<u32>(in_component);
|
||||||
const u32 half = ((tmp_word >> 16) & sign_mask) |
|
const u32 half = ((tmp_word >> 16) & sign_mask) |
|
||||||
((((tmp_word & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) |
|
((((tmp_word & 0x7f800000) - 0x38000000) >> 13) & exponent_mask) |
|
||||||
((tmp_word >> 13) & 0x03ff);
|
((tmp_word >> 13) & mantissa_mask);
|
||||||
insert_to_word(half);
|
insert_to_word(half);
|
||||||
} else {
|
} else {
|
||||||
insert_to_word(to_fp_n(in_component, component_sizes[which_component],
|
insert_to_word(to_fp_n(in_component, component_sizes[which_component],
|
||||||
|
@ -740,7 +761,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void ConvertTo(std::span<u8> input, std::span<f32> output) override {
|
void ConvertTo(std::span<const u8> input, std::span<f32> output) override {
|
||||||
const size_t num_pixels = output.size() / components_per_ir_rep;
|
const size_t num_pixels = output.size() / components_per_ir_rep;
|
||||||
for (size_t pixel = 0; pixel < num_pixels; pixel++) {
|
for (size_t pixel = 0; pixel < num_pixels; pixel++) {
|
||||||
std::array<u32, total_words_per_pixel> words{};
|
std::array<u32, total_words_per_pixel> words{};
|
||||||
|
@ -790,10 +811,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConvertFrom(std::span<f32> input, std::span<u8> output) override {
|
void ConvertFrom(std::span<const f32> input, std::span<u8> output) override {
|
||||||
const size_t num_pixels = output.size() / total_bytes_per_pixel;
|
const size_t num_pixels = output.size() / total_bytes_per_pixel;
|
||||||
for (size_t pixel = 0; pixel < num_pixels; pixel++) {
|
for (size_t pixel = 0; pixel < num_pixels; pixel++) {
|
||||||
std::span<f32> old_components(&input[pixel * components_per_ir_rep],
|
std::span<const f32> old_components(&input[pixel * components_per_ir_rep],
|
||||||
components_per_ir_rep);
|
components_per_ir_rep);
|
||||||
std::array<u32, total_words_per_pixel> words{};
|
std::array<u32, total_words_per_pixel> words{};
|
||||||
if constexpr (component_swizzle[0] != Swizzle::None) {
|
if constexpr (component_swizzle[0] != Swizzle::None) {
|
||||||
|
@ -827,7 +848,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ConverterImpl() = default;
|
ConverterImpl() = default;
|
||||||
~ConverterImpl() = default;
|
~ConverterImpl() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConverterFactory::ConverterFactoryImpl {
|
struct ConverterFactory::ConverterFactoryImpl {
|
||||||
|
@ -850,13 +871,15 @@ Converter* ConverterFactory::GetFormatConverter(RenderTargetFormat format) {
|
||||||
|
|
||||||
class NullConverter : public Converter {
|
class NullConverter : public Converter {
|
||||||
public:
|
public:
|
||||||
void ConvertTo([[maybe_unused]] std::span<u8> input, std::span<f32> output) override {
|
void ConvertTo([[maybe_unused]] std::span<const u8> input, std::span<f32> output) override {
|
||||||
std::fill(output.begin(), output.end(), 0.0f);
|
std::fill(output.begin(), output.end(), 0.0f);
|
||||||
}
|
}
|
||||||
void ConvertFrom([[maybe_unused]] std::span<f32> input, std::span<u8> output) override {
|
void ConvertFrom([[maybe_unused]] std::span<const f32> input, std::span<u8> output) override {
|
||||||
const u8 fill_value = 0U;
|
const u8 fill_value = 0U;
|
||||||
std::fill(output.begin(), output.end(), fill_value);
|
std::fill(output.begin(), output.end(), fill_value);
|
||||||
}
|
}
|
||||||
|
NullConverter() = default;
|
||||||
|
~NullConverter() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
Converter* ConverterFactory::BuildConverter(RenderTargetFormat format) {
|
Converter* ConverterFactory::BuildConverter(RenderTargetFormat format) {
|
||||||
|
@ -1011,6 +1034,16 @@ Converter* ConverterFactory::BuildConverter(RenderTargetFormat format) {
|
||||||
.emplace(format, std::make_unique<ConverterImpl<R32_FLOATTraits>>())
|
.emplace(format, std::make_unique<ConverterImpl<R32_FLOATTraits>>())
|
||||||
.first->second.get();
|
.first->second.get();
|
||||||
break;
|
break;
|
||||||
|
case RenderTargetFormat::X8R8G8B8_UNORM:
|
||||||
|
return impl->converters_cache
|
||||||
|
.emplace(format, std::make_unique<ConverterImpl<X8R8G8B8_UNORMTraits>>())
|
||||||
|
.first->second.get();
|
||||||
|
break;
|
||||||
|
case RenderTargetFormat::X8R8G8B8_SRGB:
|
||||||
|
return impl->converters_cache
|
||||||
|
.emplace(format, std::make_unique<ConverterImpl<X8R8G8B8_SRGBTraits>>())
|
||||||
|
.first->second.get();
|
||||||
|
break;
|
||||||
case RenderTargetFormat::R5G6B5_UNORM:
|
case RenderTargetFormat::R5G6B5_UNORM:
|
||||||
return impl->converters_cache
|
return impl->converters_cache
|
||||||
.emplace(format, std::make_unique<ConverterImpl<R5G6B5_UNORMTraits>>())
|
.emplace(format, std::make_unique<ConverterImpl<R5G6B5_UNORMTraits>>())
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
|
|
||||||
namespace Tegra::Engines::Blitter {
|
namespace Tegra::Engines::Blitter {
|
||||||
|
|
||||||
class Converter {
|
class Converter {
|
||||||
public:
|
public:
|
||||||
virtual void ConvertTo(std::span<u8> input, std::span<f32> output) = 0;
|
virtual void ConvertTo(std::span<const u8> input, std::span<f32> output) = 0;
|
||||||
virtual void ConvertFrom(std::span<f32> input, std::span<u8> output) = 0;
|
virtual void ConvertFrom(std::span<const f32> input, std::span<u8> output) = 0;
|
||||||
|
virtual ~Converter() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConverterFactory {
|
class ConverterFactory {
|
||||||
|
|
|
@ -61,8 +61,8 @@ enum class RenderTargetFormat : u32 {
|
||||||
R32_SINT = 0xE3,
|
R32_SINT = 0xE3,
|
||||||
R32_UINT = 0xE4,
|
R32_UINT = 0xE4,
|
||||||
R32_FLOAT = 0xE5,
|
R32_FLOAT = 0xE5,
|
||||||
// X8R8G8B8_UNORM = 0xE6,
|
X8R8G8B8_UNORM = 0xE6,
|
||||||
// X8R8G8B8_SRGB = 0xE7,
|
X8R8G8B8_SRGB = 0xE7,
|
||||||
R5G6B5_UNORM = 0xE8,
|
R5G6B5_UNORM = 0xE8,
|
||||||
A1R5G5B5_UNORM = 0xE9,
|
A1R5G5B5_UNORM = 0xE9,
|
||||||
R8G8_UNORM = 0xEA,
|
R8G8_UNORM = 0xEA,
|
||||||
|
|
|
@ -118,8 +118,10 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format)
|
||||||
case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
|
case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
|
||||||
return PixelFormat::R16G16B16X16_FLOAT;
|
return PixelFormat::R16G16B16X16_FLOAT;
|
||||||
case Tegra::RenderTargetFormat::A8R8G8B8_UNORM:
|
case Tegra::RenderTargetFormat::A8R8G8B8_UNORM:
|
||||||
|
case Tegra::RenderTargetFormat::X8R8G8B8_UNORM:
|
||||||
return PixelFormat::B8G8R8A8_UNORM;
|
return PixelFormat::B8G8R8A8_UNORM;
|
||||||
case Tegra::RenderTargetFormat::A8R8G8B8_SRGB:
|
case Tegra::RenderTargetFormat::A8R8G8B8_SRGB:
|
||||||
|
case Tegra::RenderTargetFormat::X8R8G8B8_SRGB:
|
||||||
return PixelFormat::B8G8R8A8_SRGB;
|
return PixelFormat::B8G8R8A8_SRGB;
|
||||||
case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
|
case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
|
||||||
return PixelFormat::A2B10G10R10_UNORM;
|
return PixelFormat::A2B10G10R10_UNORM;
|
||||||
|
|
Reference in New Issue