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