summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2022-11-06 11:08:22 +0100
committerGravatar Fernando Sahmkow2022-11-24 20:35:44 +0100
commit5fbd6954efbfe3dd95fcd496cd25664c092947fc (patch)
treeca9c4a7e1855b4406531eada1e84b6cb26802122
parentFermi2D: Rework blit engine and add a software blitter. (diff)
downloadyuzu-5fbd6954efbfe3dd95fcd496cd25664c092947fc.tar.gz
yuzu-5fbd6954efbfe3dd95fcd496cd25664c092947fc.tar.xz
yuzu-5fbd6954efbfe3dd95fcd496cd25664c092947fc.zip
Fermi2D: Implement Bilinear software filtering and address feedback.
-rw-r--r--src/video_core/engines/fermi_2d.cpp11
-rw-r--r--src/video_core/engines/sw_blitter/blitter.cpp97
-rw-r--r--src/video_core/engines/sw_blitter/blitter.h2
-rw-r--r--src/video_core/engines/sw_blitter/converter.cpp171
-rw-r--r--src/video_core/engines/sw_blitter/converter.h9
-rw-r--r--src/video_core/gpu.h4
-rw-r--r--src/video_core/surface.cpp2
7 files changed, 180 insertions, 116 deletions
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 2c722c778..c6478ae85 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -62,11 +62,15 @@ void Fermi2D::Blit() {
62 62
63 const auto& args = regs.pixels_from_memory; 63 const auto& args = regs.pixels_from_memory;
64 constexpr s64 null_derivate = 1ULL << 32; 64 constexpr s64 null_derivate = 1ULL << 32;
65 Surface src = regs.src;
66 const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format));
67 const bool delegate_to_gpu = src.width > 512 && src.height > 512 && bytes_per_pixel <= 8 &&
68 src.format != regs.dst.format;
65 Config config{ 69 Config config{
66 .operation = regs.operation, 70 .operation = regs.operation,
67 .filter = args.sample_mode.filter, 71 .filter = args.sample_mode.filter,
68 .must_accelerate = args.du_dx != null_derivate || args.dv_dy != null_derivate || 72 .must_accelerate =
69 args.sample_mode.filter == Filter::Bilinear, 73 args.du_dx != null_derivate || args.dv_dy != null_derivate || delegate_to_gpu,
70 .dst_x0 = args.dst_x0, 74 .dst_x0 = args.dst_x0,
71 .dst_y0 = args.dst_y0, 75 .dst_y0 = args.dst_y0,
72 .dst_x1 = args.dst_x0 + args.dst_width, 76 .dst_x1 = args.dst_x0 + args.dst_width,
@@ -76,8 +80,7 @@ void Fermi2D::Blit() {
76 .src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32), 80 .src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32),
77 .src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32), 81 .src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32),
78 }; 82 };
79 Surface src = regs.src; 83
80 const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format));
81 const auto need_align_to_pitch = 84 const auto need_align_to_pitch =
82 src.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch && 85 src.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch &&
83 static_cast<s32>(src.width) == config.src_x1 && 86 static_cast<s32>(src.width) == config.src_x1 &&
diff --git a/src/video_core/engines/sw_blitter/blitter.cpp b/src/video_core/engines/sw_blitter/blitter.cpp
index caf51cbe3..c923a80e9 100644
--- a/src/video_core/engines/sw_blitter/blitter.cpp
+++ b/src/video_core/engines/sw_blitter/blitter.cpp
@@ -1,6 +1,8 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include <algorithm>
5#include <cmath>
4#include <vector> 6#include <vector>
5 7
6#include "video_core/engines/sw_blitter/blitter.h" 8#include "video_core/engines/sw_blitter/blitter.h"
@@ -22,8 +24,10 @@ using namespace Texture;
22 24
23namespace { 25namespace {
24 26
25void NeighrestNeighbor(std::span<u8> input, std::span<u8> output, u32 src_width, u32 src_height, 27constexpr size_t ir_components = 4;
26 u32 dst_width, u32 dst_height, size_t bpp) { 28
29void NeighrestNeighbor(std::span<const u8> input, std::span<u8> output, u32 src_width,
30 u32 src_height, u32 dst_width, u32 dst_height, size_t bpp) {
27 const size_t dx_du = std::llround((static_cast<f64>(src_width) / dst_width) * (1ULL << 32)); 31 const size_t dx_du = std::llround((static_cast<f64>(src_width) / dst_width) * (1ULL << 32));
28 const size_t dy_dv = std::llround((static_cast<f64>(src_height) / dst_height) * (1ULL << 32)); 32 const size_t dy_dv = std::llround((static_cast<f64>(src_height) / dst_height) * (1ULL << 32));
29 size_t src_y = 0; 33 size_t src_y = 0;
@@ -40,7 +44,7 @@ void NeighrestNeighbor(std::span<u8> input, std::span<u8> output, u32 src_width,
40 } 44 }
41} 45}
42 46
43void NeighrestNeighborFast(std::span<f32> input, std::span<f32> output, u32 src_width, 47void NeighrestNeighborFast(std::span<const f32> input, std::span<f32> output, u32 src_width,
44 u32 src_height, u32 dst_width, u32 dst_height) { 48 u32 src_height, u32 dst_width, u32 dst_height) {
45 const size_t dx_du = std::llround((static_cast<f64>(src_width) / dst_width) * (1ULL << 32)); 49 const size_t dx_du = std::llround((static_cast<f64>(src_width) / dst_width) * (1ULL << 32));
46 const size_t dy_dv = std::llround((static_cast<f64>(src_height) / dst_height) * (1ULL << 32)); 50 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_
48 for (u32 y = 0; y < dst_height; y++) { 52 for (u32 y = 0; y < dst_height; y++) {
49 size_t src_x = 0; 53 size_t src_x = 0;
50 for (u32 x = 0; x < dst_width; x++) { 54 for (u32 x = 0; x < dst_width; x++) {
51 const size_t read_from = ((src_y * src_width + src_x) >> 32) * 4; 55 const size_t read_from = ((src_y * src_width + src_x) >> 32) * ir_components;
52 const size_t write_to = (y * dst_width + x) * 4; 56 const size_t write_to = (y * dst_width + x) * ir_components;
53 57
54 std::memcpy(&output[write_to], &input[read_from], sizeof(f32) * 4); 58 std::memcpy(&output[write_to], &input[read_from], sizeof(f32) * ir_components);
55 src_x += dx_du; 59 src_x += dx_du;
56 } 60 }
57 src_y += dy_dv; 61 src_y += dy_dv;
58 } 62 }
59} 63}
60 64
61/* 65void Bilinear(std::span<const f32> input, std::span<f32> output, size_t src_width,
62void Bilinear(std::span<f32> input, std::span<f32> output, size_t src_width, 66 size_t src_height, size_t dst_width, size_t dst_height) {
63 size_t src_height, size_t dst_width, size_t dst_height) { 67 const auto bilinear_sample = [](std::span<const f32> x0_y0, std::span<const f32> x1_y0,
64 const auto inv_lerp = [](u32 coord, u32 end) { return 68 std::span<const f32> x0_y1, std::span<const f32> x1_y1,
65static_cast<f32>(std::min(std::max(static_cast<s32>(coord), 0), end - 1)) / (end); }; 69 f32 weight_x, f32 weight_y) {
66 70 std::array<f32, ir_components> result{};
67 71 for (size_t i = 0; i < ir_components; i++) {
72 const f32 a = std::lerp(x0_y0[i], x1_y0[i], weight_x);
73 const f32 b = std::lerp(x0_y1[i], x1_y1[i], weight_x);
74 result[i] = std::lerp(a, b, weight_y);
75 }
76 return result;
77 };
78 const f32 dx_du =
79 dst_width > 1 ? static_cast<f32>(src_width - 1) / static_cast<f32>(dst_width - 1) : 0.f;
80 const f32 dy_dv =
81 dst_height > 1 ? static_cast<f32>(src_height - 1) / static_cast<f32>(dst_height - 1) : 0.f;
68 for (u32 y = 0; y < dst_height; y++) { 82 for (u32 y = 0; y < dst_height; y++) {
69 const f32 ty_0 = inv_lerp(y, dst_extent_y);
70 const f32 ty_1 = inv_lerp(y + 1, dst_extent_y);
71 for (u32 x = 0; x < dst_width; x++) { 83 for (u32 x = 0; x < dst_width; x++) {
72 const f32 tx_0 = inv_lerp(x, dst_extent_x); 84 const f32 x_low = std::floor(static_cast<f32>(x) * dx_du);
73 const f32 tx_1 = inv_lerp(x + 1, dst_extent_x); 85 const f32 y_low = std::floor(static_cast<f32>(y) * dy_dv);
74 const std::array<f32, 4> get_pixel = [&](f32 tx, f32 ty, u32 width, u32 height) { 86 const f32 x_high = std::ceil(static_cast<f32>(x) * dx_du);
75 std::array<f32, 4> result{}; 87 const f32 y_high = std::ceil(static_cast<f32>(y) * dy_dv);
76 88 const f32 weight_x = (static_cast<f32>(x) * dx_du) - x_low;
77 return (std::llround(width * tx) + std::llround(height * ty) * width) * 4; 89 const f32 weight_y = (static_cast<f32>(y) * dy_dv) - y_low;
90
91 const auto read_src = [&](f32 in_x, f32 in_y) {
92 const size_t read_from =
93 ((static_cast<size_t>(in_x) * src_width + static_cast<size_t>(in_y)) >> 32) *
94 ir_components;
95 return std::span<const f32>(&input[read_from], ir_components);
78 }; 96 };
79 std::array<f32, 4> result{};
80 97
81 const size_t read_from = get_pixel(src_width, src_height); 98 auto x0_y0 = read_src(x_low, y_low);
82 const size_t write_to = get_pixel(tx_0, ty_0, dst_width, dst_height); 99 auto x1_y0 = read_src(x_high, y_low);
100 auto x0_y1 = read_src(x_low, y_high);
101 auto x1_y1 = read_src(x_high, y_high);
83 102
84 std::memcpy(&output[write_to], &input[read_from], bpp); 103 const auto result = bilinear_sample(x0_y0, x1_y0, x0_y1, x1_y1, weight_x, weight_y);
104
105 const size_t write_to = (y * dst_width + x) * ir_components;
106
107 std::memcpy(&output[write_to], &result, sizeof(f32) * ir_components);
85 } 108 }
86 } 109 }
87} 110}
88*/
89 111
90} // namespace 112} // namespace
91 113
@@ -107,8 +129,6 @@ SoftwareBlitEngine::~SoftwareBlitEngine() = default;
107 129
108bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst, 130bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
109 Fermi2D::Config& config) { 131 Fermi2D::Config& config) {
110 UNIMPLEMENTED_IF(config.filter == Fermi2D::Filter::Bilinear);
111
112 const auto get_surface_size = [](Fermi2D::Surface& surface, u32 bytes_per_pixel) { 132 const auto get_surface_size = [](Fermi2D::Surface& surface, u32 bytes_per_pixel) {
113 if (surface.linear == Fermi2D::MemoryLayout::BlockLinear) { 133 if (surface.linear == Fermi2D::MemoryLayout::BlockLinear) {
114 return CalculateSize(true, bytes_per_pixel, surface.width, surface.height, 134 return CalculateSize(true, bytes_per_pixel, surface.width, surface.height,
@@ -116,9 +136,9 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
116 } 136 }
117 return static_cast<size_t>(surface.pitch * surface.height); 137 return static_cast<size_t>(surface.pitch * surface.height);
118 }; 138 };
119 const auto process_pitch_linear = [](bool unpack, std::span<u8> input, std::span<u8> output, 139 const auto process_pitch_linear = [](bool unpack, std::span<const u8> input,
120 u32 extent_x, u32 extent_y, u32 pitch, u32 x0, u32 y0, 140 std::span<u8> output, u32 extent_x, u32 extent_y,
121 size_t bpp) { 141 u32 pitch, u32 x0, u32 y0, size_t bpp) {
122 const size_t base_offset = x0 * bpp; 142 const size_t base_offset = x0 * bpp;
123 const size_t copy_size = extent_x * bpp; 143 const size_t copy_size = extent_x * bpp;
124 for (u32 y = y0; y < extent_y; y++) { 144 for (u32 y = y0; y < extent_y; y++) {
@@ -157,12 +177,17 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
157 177
158 const auto convertion_phase_ir = [&]() { 178 const auto convertion_phase_ir = [&]() {
159 auto* input_converter = impl->converter_factory.GetFormatConverter(src.format); 179 auto* input_converter = impl->converter_factory.GetFormatConverter(src.format);
160 impl->intermediate_src.resize((src_copy_size / src_bytes_per_pixel) * 4); 180 impl->intermediate_src.resize((src_copy_size / src_bytes_per_pixel) * ir_components);
161 impl->intermediate_dst.resize((dst_copy_size / dst_bytes_per_pixel) * 4); 181 impl->intermediate_dst.resize((dst_copy_size / dst_bytes_per_pixel) * ir_components);
162 input_converter->ConvertTo(impl->src_buffer, impl->intermediate_src); 182 input_converter->ConvertTo(impl->src_buffer, impl->intermediate_src);
163 183
164 NeighrestNeighborFast(impl->intermediate_src, impl->intermediate_dst, src_extent_x, 184 if (config.filter != Fermi2D::Filter::Bilinear) {
165 src_extent_y, dst_extent_x, dst_extent_y); 185 NeighrestNeighborFast(impl->intermediate_src, impl->intermediate_dst, src_extent_x,
186 src_extent_y, dst_extent_x, dst_extent_y);
187 } else {
188 Bilinear(impl->intermediate_src, impl->intermediate_dst, src_extent_x, src_extent_y,
189 dst_extent_x, dst_extent_y);
190 }
166 191
167 auto* output_converter = impl->converter_factory.GetFormatConverter(dst.format); 192 auto* output_converter = impl->converter_factory.GetFormatConverter(dst.format);
168 output_converter->ConvertFrom(impl->intermediate_dst, impl->dst_buffer); 193 output_converter->ConvertFrom(impl->intermediate_dst, impl->dst_buffer);
@@ -183,7 +208,7 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
183 208
184 // Conversion Phase 209 // Conversion Phase
185 if (no_passthrough) { 210 if (no_passthrough) {
186 if (src.format != dst.format) { 211 if (src.format != dst.format || config.filter == Fermi2D::Filter::Bilinear) {
187 convertion_phase_ir(); 212 convertion_phase_ir();
188 } else { 213 } else {
189 convertion_phase_same_format(); 214 convertion_phase_same_format();
diff --git a/src/video_core/engines/sw_blitter/blitter.h b/src/video_core/engines/sw_blitter/blitter.h
index 3edf40c3e..85b55c836 100644
--- a/src/video_core/engines/sw_blitter/blitter.h
+++ b/src/video_core/engines/sw_blitter/blitter.h
@@ -13,7 +13,7 @@ namespace Tegra::Engines::Blitter {
13 13
14class SoftwareBlitEngine { 14class SoftwareBlitEngine {
15public: 15public:
16 SoftwareBlitEngine(MemoryManager& memory_manager_); 16 explicit SoftwareBlitEngine(MemoryManager& memory_manager_);
17 ~SoftwareBlitEngine(); 17 ~SoftwareBlitEngine();
18 18
19 bool Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst, Fermi2D::Config& copy_config); 19 bool Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst, Fermi2D::Config& copy_config);
diff --git a/src/video_core/engines/sw_blitter/converter.cpp b/src/video_core/engines/sw_blitter/converter.cpp
index 2e376f430..408d87944 100644
--- a/src/video_core/engines/sw_blitter/converter.cpp
+++ b/src/video_core/engines/sw_blitter/converter.cpp
@@ -139,7 +139,7 @@ struct R32B32G32A32_FLOATTraits {
139 ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT}; 139 ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
140 static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32}; 140 static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
141 static constexpr std::array<Swizzle, num_components> component_swizzle = { 141 static constexpr std::array<Swizzle, num_components> component_swizzle = {
142 Swizzle::A, Swizzle::G, Swizzle::B, Swizzle::R}; 142 Swizzle::R, Swizzle::B, Swizzle::G, Swizzle::A};
143}; 143};
144 144
145struct R32G32B32A32_SINTTraits { 145struct R32G32B32A32_SINTTraits {
@@ -148,7 +148,7 @@ struct R32G32B32A32_SINTTraits {
148 ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT}; 148 ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
149 static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32}; 149 static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
150 static constexpr std::array<Swizzle, num_components> component_swizzle = { 150 static constexpr std::array<Swizzle, num_components> component_swizzle = {
151 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R}; 151 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
152}; 152};
153 153
154struct R32G32B32A32_UINTTraits { 154struct R32G32B32A32_UINTTraits {
@@ -157,7 +157,7 @@ struct R32G32B32A32_UINTTraits {
157 ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT}; 157 ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
158 static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32}; 158 static constexpr std::array<size_t, num_components> component_sizes = {32, 32, 32, 32};
159 static constexpr std::array<Swizzle, num_components> component_swizzle = { 159 static constexpr std::array<Swizzle, num_components> component_swizzle = {
160 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R}; 160 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
161}; 161};
162 162
163struct R16G16B16A16_UNORMTraits { 163struct R16G16B16A16_UNORMTraits {
@@ -166,7 +166,7 @@ struct R16G16B16A16_UNORMTraits {
166 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM}; 166 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
167 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16}; 167 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
168 static constexpr std::array<Swizzle, num_components> component_swizzle = { 168 static constexpr std::array<Swizzle, num_components> component_swizzle = {
169 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R}; 169 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
170}; 170};
171 171
172struct R16G16B16A16_SNORMTraits { 172struct R16G16B16A16_SNORMTraits {
@@ -175,7 +175,7 @@ struct R16G16B16A16_SNORMTraits {
175 ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM}; 175 ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM};
176 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16}; 176 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
177 static constexpr std::array<Swizzle, num_components> component_swizzle = { 177 static constexpr std::array<Swizzle, num_components> component_swizzle = {
178 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R}; 178 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
179}; 179};
180 180
181struct R16G16B16A16_SINTTraits { 181struct R16G16B16A16_SINTTraits {
@@ -184,7 +184,7 @@ struct R16G16B16A16_SINTTraits {
184 ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT}; 184 ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
185 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16}; 185 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
186 static constexpr std::array<Swizzle, num_components> component_swizzle = { 186 static constexpr std::array<Swizzle, num_components> component_swizzle = {
187 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R}; 187 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
188}; 188};
189 189
190struct R16G16B16A16_UINTTraits { 190struct R16G16B16A16_UINTTraits {
@@ -193,7 +193,7 @@ struct R16G16B16A16_UINTTraits {
193 ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT}; 193 ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
194 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16}; 194 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
195 static constexpr std::array<Swizzle, num_components> component_swizzle = { 195 static constexpr std::array<Swizzle, num_components> component_swizzle = {
196 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R}; 196 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
197}; 197};
198 198
199struct R16G16B16A16_FLOATTraits { 199struct R16G16B16A16_FLOATTraits {
@@ -202,7 +202,7 @@ struct R16G16B16A16_FLOATTraits {
202 ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT}; 202 ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
203 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16}; 203 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
204 static constexpr std::array<Swizzle, num_components> component_swizzle = { 204 static constexpr std::array<Swizzle, num_components> component_swizzle = {
205 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R}; 205 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A};
206}; 206};
207 207
208struct R32G32_FLOATTraits { 208struct R32G32_FLOATTraits {
@@ -210,8 +210,8 @@ struct R32G32_FLOATTraits {
210 static constexpr std::array<ComponentType, num_components> component_types = { 210 static constexpr std::array<ComponentType, num_components> component_types = {
211 ComponentType::FLOAT, ComponentType::FLOAT}; 211 ComponentType::FLOAT, ComponentType::FLOAT};
212 static constexpr std::array<size_t, num_components> component_sizes = {32, 32}; 212 static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
213 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 213 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
214 Swizzle::R}; 214 Swizzle::G};
215}; 215};
216 216
217struct R32G32_SINTTraits { 217struct R32G32_SINTTraits {
@@ -219,8 +219,8 @@ struct R32G32_SINTTraits {
219 static constexpr std::array<ComponentType, num_components> component_types = { 219 static constexpr std::array<ComponentType, num_components> component_types = {
220 ComponentType::SINT, ComponentType::SINT}; 220 ComponentType::SINT, ComponentType::SINT};
221 static constexpr std::array<size_t, num_components> component_sizes = {32, 32}; 221 static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
222 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 222 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
223 Swizzle::R}; 223 Swizzle::G};
224}; 224};
225 225
226struct R32G32_UINTTraits { 226struct R32G32_UINTTraits {
@@ -228,8 +228,8 @@ struct R32G32_UINTTraits {
228 static constexpr std::array<ComponentType, num_components> component_types = { 228 static constexpr std::array<ComponentType, num_components> component_types = {
229 ComponentType::UINT, ComponentType::UINT}; 229 ComponentType::UINT, ComponentType::UINT};
230 static constexpr std::array<size_t, num_components> component_sizes = {32, 32}; 230 static constexpr std::array<size_t, num_components> component_sizes = {32, 32};
231 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 231 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
232 Swizzle::R}; 232 Swizzle::G};
233}; 233};
234 234
235struct R16G16B16X16_FLOATTraits { 235struct R16G16B16X16_FLOATTraits {
@@ -238,7 +238,7 @@ struct R16G16B16X16_FLOATTraits {
238 ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT}; 238 ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
239 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16}; 239 static constexpr std::array<size_t, num_components> component_sizes = {16, 16, 16, 16};
240 static constexpr std::array<Swizzle, num_components> component_swizzle = { 240 static constexpr std::array<Swizzle, num_components> component_swizzle = {
241 Swizzle::None, Swizzle::B, Swizzle::G, Swizzle::R}; 241 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::None};
242}; 242};
243 243
244struct A8R8G8B8_UNORMTraits { 244struct A8R8G8B8_UNORMTraits {
@@ -247,7 +247,7 @@ struct A8R8G8B8_UNORMTraits {
247 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM}; 247 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
248 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8}; 248 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
249 static constexpr std::array<Swizzle, num_components> component_swizzle = { 249 static constexpr std::array<Swizzle, num_components> component_swizzle = {
250 Swizzle::B, Swizzle::G, Swizzle::R, Swizzle::A}; 250 Swizzle::A, Swizzle::R, Swizzle::G, Swizzle::B};
251}; 251};
252 252
253struct A8R8G8B8_SRGBTraits { 253struct A8R8G8B8_SRGBTraits {
@@ -256,25 +256,25 @@ struct A8R8G8B8_SRGBTraits {
256 ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB}; 256 ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB};
257 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8}; 257 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
258 static constexpr std::array<Swizzle, num_components> component_swizzle = { 258 static constexpr std::array<Swizzle, num_components> component_swizzle = {
259 Swizzle::B, Swizzle::G, Swizzle::R, Swizzle::A}; 259 Swizzle::A, Swizzle::R, Swizzle::G, Swizzle::B};
260}; 260};
261 261
262struct A2B10G10R10_UNORMTraits { 262struct A2B10G10R10_UNORMTraits {
263 static constexpr size_t num_components = 4; 263 static constexpr size_t num_components = 4;
264 static constexpr std::array<ComponentType, num_components> component_types = { 264 static constexpr std::array<ComponentType, num_components> component_types = {
265 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM}; 265 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
266 static constexpr std::array<size_t, num_components> component_sizes = {10, 10, 10, 2}; 266 static constexpr std::array<size_t, num_components> component_sizes = {2, 10, 10, 10};
267 static constexpr std::array<Swizzle, num_components> component_swizzle = { 267 static constexpr std::array<Swizzle, num_components> component_swizzle = {
268 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A}; 268 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
269}; 269};
270 270
271struct A2B10G10R10_UINTTraits { 271struct A2B10G10R10_UINTTraits {
272 static constexpr size_t num_components = 4; 272 static constexpr size_t num_components = 4;
273 static constexpr std::array<ComponentType, num_components> component_types = { 273 static constexpr std::array<ComponentType, num_components> component_types = {
274 ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT}; 274 ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
275 static constexpr std::array<size_t, num_components> component_sizes = {10, 10, 10, 2}; 275 static constexpr std::array<size_t, num_components> component_sizes = {2, 10, 10, 10};
276 static constexpr std::array<Swizzle, num_components> component_swizzle = { 276 static constexpr std::array<Swizzle, num_components> component_swizzle = {
277 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A}; 277 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
278}; 278};
279 279
280struct A8B8G8R8_UNORMTraits { 280struct A8B8G8R8_UNORMTraits {
@@ -283,7 +283,7 @@ struct A8B8G8R8_UNORMTraits {
283 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM}; 283 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
284 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8}; 284 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
285 static constexpr std::array<Swizzle, num_components> component_swizzle = { 285 static constexpr std::array<Swizzle, num_components> component_swizzle = {
286 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A}; 286 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
287}; 287};
288 288
289struct A8B8G8R8_SRGBTraits { 289struct A8B8G8R8_SRGBTraits {
@@ -292,7 +292,7 @@ struct A8B8G8R8_SRGBTraits {
292 ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB}; 292 ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB};
293 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8}; 293 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
294 static constexpr std::array<Swizzle, num_components> component_swizzle = { 294 static constexpr std::array<Swizzle, num_components> component_swizzle = {
295 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A}; 295 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
296}; 296};
297 297
298struct A8B8G8R8_SNORMTraits { 298struct A8B8G8R8_SNORMTraits {
@@ -301,7 +301,7 @@ struct A8B8G8R8_SNORMTraits {
301 ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM}; 301 ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM, ComponentType::SNORM};
302 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8}; 302 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
303 static constexpr std::array<Swizzle, num_components> component_swizzle = { 303 static constexpr std::array<Swizzle, num_components> component_swizzle = {
304 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A}; 304 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
305}; 305};
306 306
307struct A8B8G8R8_SINTTraits { 307struct A8B8G8R8_SINTTraits {
@@ -310,7 +310,7 @@ struct A8B8G8R8_SINTTraits {
310 ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT}; 310 ComponentType::SINT, ComponentType::SINT, ComponentType::SINT, ComponentType::SINT};
311 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8}; 311 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
312 static constexpr std::array<Swizzle, num_components> component_swizzle = { 312 static constexpr std::array<Swizzle, num_components> component_swizzle = {
313 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A}; 313 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
314}; 314};
315 315
316struct A8B8G8R8_UINTTraits { 316struct A8B8G8R8_UINTTraits {
@@ -319,7 +319,7 @@ struct A8B8G8R8_UINTTraits {
319 ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT}; 319 ComponentType::UINT, ComponentType::UINT, ComponentType::UINT, ComponentType::UINT};
320 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8}; 320 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
321 static constexpr std::array<Swizzle, num_components> component_swizzle = { 321 static constexpr std::array<Swizzle, num_components> component_swizzle = {
322 Swizzle::R, Swizzle::G, Swizzle::B, Swizzle::A}; 322 Swizzle::A, Swizzle::B, Swizzle::G, Swizzle::R};
323}; 323};
324 324
325struct R16G16_UNORMTraits { 325struct R16G16_UNORMTraits {
@@ -327,8 +327,8 @@ struct R16G16_UNORMTraits {
327 static constexpr std::array<ComponentType, num_components> component_types = { 327 static constexpr std::array<ComponentType, num_components> component_types = {
328 ComponentType::UNORM, ComponentType::UNORM}; 328 ComponentType::UNORM, ComponentType::UNORM};
329 static constexpr std::array<size_t, num_components> component_sizes = {16, 16}; 329 static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
330 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 330 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
331 Swizzle::R}; 331 Swizzle::G};
332}; 332};
333 333
334struct R16G16_SNORMTraits { 334struct R16G16_SNORMTraits {
@@ -336,8 +336,8 @@ struct R16G16_SNORMTraits {
336 static constexpr std::array<ComponentType, num_components> component_types = { 336 static constexpr std::array<ComponentType, num_components> component_types = {
337 ComponentType::SNORM, ComponentType::SNORM}; 337 ComponentType::SNORM, ComponentType::SNORM};
338 static constexpr std::array<size_t, num_components> component_sizes = {16, 16}; 338 static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
339 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 339 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
340 Swizzle::R}; 340 Swizzle::G};
341}; 341};
342 342
343struct R16G16_SINTTraits { 343struct R16G16_SINTTraits {
@@ -345,8 +345,8 @@ struct R16G16_SINTTraits {
345 static constexpr std::array<ComponentType, num_components> component_types = { 345 static constexpr std::array<ComponentType, num_components> component_types = {
346 ComponentType::SINT, ComponentType::SINT}; 346 ComponentType::SINT, ComponentType::SINT};
347 static constexpr std::array<size_t, num_components> component_sizes = {16, 16}; 347 static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
348 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 348 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
349 Swizzle::R}; 349 Swizzle::G};
350}; 350};
351 351
352struct R16G16_UINTTraits { 352struct R16G16_UINTTraits {
@@ -354,8 +354,8 @@ struct R16G16_UINTTraits {
354 static constexpr std::array<ComponentType, num_components> component_types = { 354 static constexpr std::array<ComponentType, num_components> component_types = {
355 ComponentType::UINT, ComponentType::UINT}; 355 ComponentType::UINT, ComponentType::UINT};
356 static constexpr std::array<size_t, num_components> component_sizes = {16, 16}; 356 static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
357 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 357 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
358 Swizzle::R}; 358 Swizzle::G};
359}; 359};
360 360
361struct R16G16_FLOATTraits { 361struct R16G16_FLOATTraits {
@@ -363,17 +363,17 @@ struct R16G16_FLOATTraits {
363 static constexpr std::array<ComponentType, num_components> component_types = { 363 static constexpr std::array<ComponentType, num_components> component_types = {
364 ComponentType::FLOAT, ComponentType::FLOAT}; 364 ComponentType::FLOAT, ComponentType::FLOAT};
365 static constexpr std::array<size_t, num_components> component_sizes = {16, 16}; 365 static constexpr std::array<size_t, num_components> component_sizes = {16, 16};
366 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 366 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
367 Swizzle::R}; 367 Swizzle::G};
368}; 368};
369 369
370struct B10G11R11_FLOATTraits { 370struct B10G11R11_FLOATTraits {
371 static constexpr size_t num_components = 3; 371 static constexpr size_t num_components = 3;
372 static constexpr std::array<ComponentType, num_components> component_types = { 372 static constexpr std::array<ComponentType, num_components> component_types = {
373 ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT}; 373 ComponentType::FLOAT, ComponentType::FLOAT, ComponentType::FLOAT};
374 static constexpr std::array<size_t, num_components> component_sizes = {11, 11, 10}; 374 static constexpr std::array<size_t, num_components> component_sizes = {10, 11, 11};
375 static constexpr std::array<Swizzle, num_components> component_swizzle = { 375 static constexpr std::array<Swizzle, num_components> component_swizzle = {
376 Swizzle::R, Swizzle::G, Swizzle::B}; 376 Swizzle::B, Swizzle::G, Swizzle::R};
377}; 377};
378 378
379struct R32_SINTTraits { 379struct R32_SINTTraits {
@@ -400,22 +400,40 @@ struct R32_FLOATTraits {
400 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R}; 400 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R};
401}; 401};
402 402
403struct X8R8G8B8_UNORMTraits {
404 static constexpr size_t num_components = 4;
405 static constexpr std::array<ComponentType, num_components> component_types = {
406 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
407 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
408 static constexpr std::array<Swizzle, num_components> component_swizzle = {
409 Swizzle::None, Swizzle::R, Swizzle::G, Swizzle::B};
410};
411
412struct X8R8G8B8_SRGBTraits {
413 static constexpr size_t num_components = 4;
414 static constexpr std::array<ComponentType, num_components> component_types = {
415 ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB, ComponentType::SRGB};
416 static constexpr std::array<size_t, num_components> component_sizes = {8, 8, 8, 8};
417 static constexpr std::array<Swizzle, num_components> component_swizzle = {
418 Swizzle::None, Swizzle::R, Swizzle::G, Swizzle::B};
419};
420
403struct R5G6B5_UNORMTraits { 421struct R5G6B5_UNORMTraits {
404 static constexpr size_t num_components = 3; 422 static constexpr size_t num_components = 3;
405 static constexpr std::array<ComponentType, num_components> component_types = { 423 static constexpr std::array<ComponentType, num_components> component_types = {
406 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM}; 424 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
407 static constexpr std::array<size_t, num_components> component_sizes = {5, 6, 5}; 425 static constexpr std::array<size_t, num_components> component_sizes = {5, 6, 5};
408 static constexpr std::array<Swizzle, num_components> component_swizzle = { 426 static constexpr std::array<Swizzle, num_components> component_swizzle = {
409 Swizzle::B, Swizzle::G, Swizzle::R}; 427 Swizzle::R, Swizzle::G, Swizzle::B};
410}; 428};
411 429
412struct A1R5G5B5_UNORMTraits { 430struct A1R5G5B5_UNORMTraits {
413 static constexpr size_t num_components = 4; 431 static constexpr size_t num_components = 4;
414 static constexpr std::array<ComponentType, num_components> component_types = { 432 static constexpr std::array<ComponentType, num_components> component_types = {
415 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM}; 433 ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM, ComponentType::UNORM};
416 static constexpr std::array<size_t, num_components> component_sizes = {5, 5, 5, 1}; 434 static constexpr std::array<size_t, num_components> component_sizes = {1, 5, 5, 5};
417 static constexpr std::array<Swizzle, num_components> component_swizzle = { 435 static constexpr std::array<Swizzle, num_components> component_swizzle = {
418 Swizzle::B, Swizzle::G, Swizzle::R, Swizzle::A}; 436 Swizzle::A, Swizzle::R, Swizzle::G, Swizzle::B};
419}; 437};
420 438
421struct R8G8_UNORMTraits { 439struct R8G8_UNORMTraits {
@@ -423,8 +441,8 @@ struct R8G8_UNORMTraits {
423 static constexpr std::array<ComponentType, num_components> component_types = { 441 static constexpr std::array<ComponentType, num_components> component_types = {
424 ComponentType::UNORM, ComponentType::UNORM}; 442 ComponentType::UNORM, ComponentType::UNORM};
425 static constexpr std::array<size_t, num_components> component_sizes = {8, 8}; 443 static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
426 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 444 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
427 Swizzle::R}; 445 Swizzle::G};
428}; 446};
429 447
430struct R8G8_SNORMTraits { 448struct R8G8_SNORMTraits {
@@ -432,8 +450,8 @@ struct R8G8_SNORMTraits {
432 static constexpr std::array<ComponentType, num_components> component_types = { 450 static constexpr std::array<ComponentType, num_components> component_types = {
433 ComponentType::SNORM, ComponentType::SNORM}; 451 ComponentType::SNORM, ComponentType::SNORM};
434 static constexpr std::array<size_t, num_components> component_sizes = {8, 8}; 452 static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
435 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 453 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
436 Swizzle::R}; 454 Swizzle::G};
437}; 455};
438 456
439struct R8G8_SINTTraits { 457struct R8G8_SINTTraits {
@@ -441,8 +459,8 @@ struct R8G8_SINTTraits {
441 static constexpr std::array<ComponentType, num_components> component_types = { 459 static constexpr std::array<ComponentType, num_components> component_types = {
442 ComponentType::SINT, ComponentType::SINT}; 460 ComponentType::SINT, ComponentType::SINT};
443 static constexpr std::array<size_t, num_components> component_sizes = {8, 8}; 461 static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
444 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 462 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
445 Swizzle::R}; 463 Swizzle::G};
446}; 464};
447 465
448struct R8G8_UINTTraits { 466struct R8G8_UINTTraits {
@@ -450,8 +468,8 @@ struct R8G8_UINTTraits {
450 static constexpr std::array<ComponentType, num_components> component_types = { 468 static constexpr std::array<ComponentType, num_components> component_types = {
451 ComponentType::UINT, ComponentType::UINT}; 469 ComponentType::UINT, ComponentType::UINT};
452 static constexpr std::array<size_t, num_components> component_sizes = {8, 8}; 470 static constexpr std::array<size_t, num_components> component_sizes = {8, 8};
453 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::G, 471 static constexpr std::array<Swizzle, num_components> component_swizzle = {Swizzle::R,
454 Swizzle::R}; 472 Swizzle::G};
455}; 473};
456 474
457struct R16_UNORMTraits { 475struct R16_UNORMTraits {
@@ -611,7 +629,7 @@ private:
611 constexpr size_t fp16_mantissa_bits = 10; 629 constexpr size_t fp16_mantissa_bits = 10;
612 constexpr size_t mantissa_mask = 630 constexpr size_t mantissa_mask =
613 ~((1ULL << (fp32_mantissa_bits - fp16_mantissa_bits)) - 1ULL); 631 ~((1ULL << (fp32_mantissa_bits - fp16_mantissa_bits)) - 1ULL);
614 tmp = tmp & mantissa_mask; 632 tmp = tmp & static_cast<u32>(mantissa_mask);
615 // TODO: force the exponent within the range of half float. Not needed in UNORM / SNORM 633 // TODO: force the exponent within the range of half float. Not needed in UNORM / SNORM
616 return std::bit_cast<f32>(tmp); 634 return std::bit_cast<f32>(tmp);
617 }; 635 };
@@ -624,12 +642,13 @@ private:
624 }; 642 };
625 const auto calculate_snorm = [&]() { 643 const auto calculate_snorm = [&]() {
626 return static_cast<f32>( 644 return static_cast<f32>(
627 static_cast<f64>(sign_extend(value, component_sizes[which_component])) / 645 static_cast<f32>(sign_extend(value, component_sizes[which_component])) /
628 ((1ULL << (component_sizes[which_component] - 1ULL)) - 1ULL)); 646 static_cast<f32>((1ULL << (component_sizes[which_component] - 1ULL)) - 1ULL));
629 }; 647 };
630 const auto calculate_unorm = [&]() { 648 const auto calculate_unorm = [&]() {
631 return static_cast<f32>(static_cast<f32>(value) / 649 return static_cast<f32>(
632 ((1ULL << (component_sizes[which_component])) - 1ULL)); 650 static_cast<f32>(value) /
651 static_cast<f32>((1ULL << (component_sizes[which_component])) - 1ULL));
633 }; 652 };
634 if constexpr (component_types[which_component] == ComponentType::SNORM) { 653 if constexpr (component_types[which_component] == ComponentType::SNORM) {
635 out_component = calculate_snorm(); 654 out_component = calculate_snorm();
@@ -688,14 +707,15 @@ private:
688 return tmp_value >> shift_towards; 707 return tmp_value >> shift_towards;
689 }; 708 };
690 const auto calculate_unorm = [&]() { 709 const auto calculate_unorm = [&]() {
691 return static_cast<u32>(static_cast<f32>(in_component) * 710 return static_cast<u32>(
692 ((1ULL << (component_sizes[which_component])) - 1ULL)); 711 static_cast<f32>(in_component) *
712 static_cast<f32>((1ULL << (component_sizes[which_component])) - 1ULL));
693 }; 713 };
694 if constexpr (component_types[which_component] == ComponentType::SNORM || 714 if constexpr (component_types[which_component] == ComponentType::SNORM ||
695 component_types[which_component] == ComponentType::SNORM_FORCE_FP16) { 715 component_types[which_component] == ComponentType::SNORM_FORCE_FP16) {
696 s32 tmp_word = 716 s32 tmp_word = static_cast<s32>(
697 static_cast<s32>(static_cast<f64>(in_component) * 717 static_cast<f32>(in_component) *
698 ((1ULL << (component_sizes[which_component] - 1ULL)) - 1ULL)); 718 static_cast<f32>((1ULL << (component_sizes[which_component] - 1ULL)) - 1ULL));
699 insert_to_word(tmp_word); 719 insert_to_word(tmp_word);
700 720
701 } else if constexpr (component_types[which_component] == ComponentType::UNORM || 721 } else if constexpr (component_types[which_component] == ComponentType::UNORM ||
@@ -714,11 +734,12 @@ private:
714 insert_to_word(tmp_word); 734 insert_to_word(tmp_word);
715 } else if constexpr (component_sizes[which_component] == 16) { 735 } else if constexpr (component_sizes[which_component] == 16) {
716 static constexpr u32 sign_mask = 0x8000; 736 static constexpr u32 sign_mask = 0x8000;
717 static constexpr u32 mantissa_mask = 0x8000; 737 static constexpr u32 mantissa_mask = 0x03ff;
738 static constexpr u32 exponent_mask = 0x7c00;
718 const u32 tmp_word = std::bit_cast<u32>(in_component); 739 const u32 tmp_word = std::bit_cast<u32>(in_component);
719 const u32 half = ((tmp_word >> 16) & sign_mask) | 740 const u32 half = ((tmp_word >> 16) & sign_mask) |
720 ((((tmp_word & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | 741 ((((tmp_word & 0x7f800000) - 0x38000000) >> 13) & exponent_mask) |
721 ((tmp_word >> 13) & 0x03ff); 742 ((tmp_word >> 13) & mantissa_mask);
722 insert_to_word(half); 743 insert_to_word(half);
723 } else { 744 } else {
724 insert_to_word(to_fp_n(in_component, component_sizes[which_component], 745 insert_to_word(to_fp_n(in_component, component_sizes[which_component],
@@ -740,7 +761,7 @@ private:
740 } 761 }
741 762
742public: 763public:
743 void ConvertTo(std::span<u8> input, std::span<f32> output) override { 764 void ConvertTo(std::span<const u8> input, std::span<f32> output) override {
744 const size_t num_pixels = output.size() / components_per_ir_rep; 765 const size_t num_pixels = output.size() / components_per_ir_rep;
745 for (size_t pixel = 0; pixel < num_pixels; pixel++) { 766 for (size_t pixel = 0; pixel < num_pixels; pixel++) {
746 std::array<u32, total_words_per_pixel> words{}; 767 std::array<u32, total_words_per_pixel> words{};
@@ -790,11 +811,11 @@ public:
790 } 811 }
791 } 812 }
792 813
793 void ConvertFrom(std::span<f32> input, std::span<u8> output) override { 814 void ConvertFrom(std::span<const f32> input, std::span<u8> output) override {
794 const size_t num_pixels = output.size() / total_bytes_per_pixel; 815 const size_t num_pixels = output.size() / total_bytes_per_pixel;
795 for (size_t pixel = 0; pixel < num_pixels; pixel++) { 816 for (size_t pixel = 0; pixel < num_pixels; pixel++) {
796 std::span<f32> old_components(&input[pixel * components_per_ir_rep], 817 std::span<const f32> old_components(&input[pixel * components_per_ir_rep],
797 components_per_ir_rep); 818 components_per_ir_rep);
798 std::array<u32, total_words_per_pixel> words{}; 819 std::array<u32, total_words_per_pixel> words{};
799 if constexpr (component_swizzle[0] != Swizzle::None) { 820 if constexpr (component_swizzle[0] != Swizzle::None) {
800 ConvertFromComponent<0>(words[bound_words[0]], 821 ConvertFromComponent<0>(words[bound_words[0]],
@@ -827,7 +848,7 @@ public:
827 } 848 }
828 849
829 ConverterImpl() = default; 850 ConverterImpl() = default;
830 ~ConverterImpl() = default; 851 ~ConverterImpl() override = default;
831}; 852};
832 853
833struct ConverterFactory::ConverterFactoryImpl { 854struct ConverterFactory::ConverterFactoryImpl {
@@ -850,13 +871,15 @@ Converter* ConverterFactory::GetFormatConverter(RenderTargetFormat format) {
850 871
851class NullConverter : public Converter { 872class NullConverter : public Converter {
852public: 873public:
853 void ConvertTo([[maybe_unused]] std::span<u8> input, std::span<f32> output) override { 874 void ConvertTo([[maybe_unused]] std::span<const u8> input, std::span<f32> output) override {
854 std::fill(output.begin(), output.end(), 0.0f); 875 std::fill(output.begin(), output.end(), 0.0f);
855 } 876 }
856 void ConvertFrom([[maybe_unused]] std::span<f32> input, std::span<u8> output) override { 877 void ConvertFrom([[maybe_unused]] std::span<const f32> input, std::span<u8> output) override {
857 const u8 fill_value = 0U; 878 const u8 fill_value = 0U;
858 std::fill(output.begin(), output.end(), fill_value); 879 std::fill(output.begin(), output.end(), fill_value);
859 } 880 }
881 NullConverter() = default;
882 ~NullConverter() = default;
860}; 883};
861 884
862Converter* ConverterFactory::BuildConverter(RenderTargetFormat format) { 885Converter* ConverterFactory::BuildConverter(RenderTargetFormat format) {
@@ -1011,6 +1034,16 @@ Converter* ConverterFactory::BuildConverter(RenderTargetFormat format) {
1011 .emplace(format, std::make_unique<ConverterImpl<R32_FLOATTraits>>()) 1034 .emplace(format, std::make_unique<ConverterImpl<R32_FLOATTraits>>())
1012 .first->second.get(); 1035 .first->second.get();
1013 break; 1036 break;
1037 case RenderTargetFormat::X8R8G8B8_UNORM:
1038 return impl->converters_cache
1039 .emplace(format, std::make_unique<ConverterImpl<X8R8G8B8_UNORMTraits>>())
1040 .first->second.get();
1041 break;
1042 case RenderTargetFormat::X8R8G8B8_SRGB:
1043 return impl->converters_cache
1044 .emplace(format, std::make_unique<ConverterImpl<X8R8G8B8_SRGBTraits>>())
1045 .first->second.get();
1046 break;
1014 case RenderTargetFormat::R5G6B5_UNORM: 1047 case RenderTargetFormat::R5G6B5_UNORM:
1015 return impl->converters_cache 1048 return impl->converters_cache
1016 .emplace(format, std::make_unique<ConverterImpl<R5G6B5_UNORMTraits>>()) 1049 .emplace(format, std::make_unique<ConverterImpl<R5G6B5_UNORMTraits>>())
diff --git a/src/video_core/engines/sw_blitter/converter.h b/src/video_core/engines/sw_blitter/converter.h
index 03337e906..f9bdc516e 100644
--- a/src/video_core/engines/sw_blitter/converter.h
+++ b/src/video_core/engines/sw_blitter/converter.h
@@ -1,21 +1,22 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#pragma once
5
4#include <memory> 6#include <memory>
5#include <span> 7#include <span>
6 8
7#include "common/common_types.h" 9#include "common/common_types.h"
8 10
9#pragma once
10
11#include "video_core/gpu.h" 11#include "video_core/gpu.h"
12 12
13namespace Tegra::Engines::Blitter { 13namespace Tegra::Engines::Blitter {
14 14
15class Converter { 15class Converter {
16public: 16public:
17 virtual void ConvertTo(std::span<u8> input, std::span<f32> output) = 0; 17 virtual void ConvertTo(std::span<const u8> input, std::span<f32> output) = 0;
18 virtual void ConvertFrom(std::span<f32> input, std::span<u8> output) = 0; 18 virtual void ConvertFrom(std::span<const f32> input, std::span<u8> output) = 0;
19 virtual ~Converter() = default;
19}; 20};
20 21
21class ConverterFactory { 22class ConverterFactory {
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index d0709dc69..87ebf2054 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -61,8 +61,8 @@ enum class RenderTargetFormat : u32 {
61 R32_SINT = 0xE3, 61 R32_SINT = 0xE3,
62 R32_UINT = 0xE4, 62 R32_UINT = 0xE4,
63 R32_FLOAT = 0xE5, 63 R32_FLOAT = 0xE5,
64 // X8R8G8B8_UNORM = 0xE6, 64 X8R8G8B8_UNORM = 0xE6,
65 // X8R8G8B8_SRGB = 0xE7, 65 X8R8G8B8_SRGB = 0xE7,
66 R5G6B5_UNORM = 0xE8, 66 R5G6B5_UNORM = 0xE8,
67 A1R5G5B5_UNORM = 0xE9, 67 A1R5G5B5_UNORM = 0xE9,
68 R8G8_UNORM = 0xEA, 68 R8G8_UNORM = 0xEA,
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index 6bd133d10..80a7d908f 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -118,8 +118,10 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format)
118 case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT: 118 case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
119 return PixelFormat::R16G16B16X16_FLOAT; 119 return PixelFormat::R16G16B16X16_FLOAT;
120 case Tegra::RenderTargetFormat::A8R8G8B8_UNORM: 120 case Tegra::RenderTargetFormat::A8R8G8B8_UNORM:
121 case Tegra::RenderTargetFormat::X8R8G8B8_UNORM:
121 return PixelFormat::B8G8R8A8_UNORM; 122 return PixelFormat::B8G8R8A8_UNORM;
122 case Tegra::RenderTargetFormat::A8R8G8B8_SRGB: 123 case Tegra::RenderTargetFormat::A8R8G8B8_SRGB:
124 case Tegra::RenderTargetFormat::X8R8G8B8_SRGB:
123 return PixelFormat::B8G8R8A8_SRGB; 125 return PixelFormat::B8G8R8A8_SRGB;
124 case Tegra::RenderTargetFormat::A2B10G10R10_UNORM: 126 case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
125 return PixelFormat::A2B10G10R10_UNORM; 127 return PixelFormat::A2B10G10R10_UNORM;