summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/compatible_formats.cpp162
-rw-r--r--src/video_core/compatible_formats.h32
-rw-r--r--src/video_core/texture_cache/texture_cache.h25
4 files changed, 216 insertions, 5 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 2dc752aa9..21c46a567 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -3,6 +3,8 @@ add_library(video_core STATIC
3 buffer_cache/buffer_cache.h 3 buffer_cache/buffer_cache.h
4 buffer_cache/map_interval.cpp 4 buffer_cache/map_interval.cpp
5 buffer_cache/map_interval.h 5 buffer_cache/map_interval.h
6 compatible_formats.cpp
7 compatible_formats.h
6 dirty_flags.cpp 8 dirty_flags.cpp
7 dirty_flags.h 9 dirty_flags.h
8 dma_pusher.cpp 10 dma_pusher.cpp
diff --git a/src/video_core/compatible_formats.cpp b/src/video_core/compatible_formats.cpp
new file mode 100644
index 000000000..6c426b035
--- /dev/null
+++ b/src/video_core/compatible_formats.cpp
@@ -0,0 +1,162 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <array>
6#include <bitset>
7#include <cstddef>
8
9#include "video_core/compatible_formats.h"
10#include "video_core/surface.h"
11
12namespace VideoCore::Surface {
13
14namespace {
15
16// Compatibility table taken from Table 3.X.2 in:
17// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_view.txt
18
19constexpr std::array VIEW_CLASS_128_BITS = {
20 PixelFormat::RGBA32F,
21 PixelFormat::RGBA32UI,
22};
23// Missing formats:
24// PixelFormat::RGBA32I
25
26constexpr std::array VIEW_CLASS_96_BITS = {
27 PixelFormat::RGB32F,
28};
29// Missing formats:
30// PixelFormat::RGB32UI,
31// PixelFormat::RGB32I,
32
33constexpr std::array VIEW_CLASS_64_BITS = {
34 PixelFormat::RGBA16F, PixelFormat::RG32F, PixelFormat::RGBA16UI, PixelFormat::RG32UI,
35 PixelFormat::RGBA16U, PixelFormat::RGBA16F, PixelFormat::RGBA16S,
36};
37// Missing formats:
38// PixelFormat::RGBA16I
39// PixelFormat::RG32I
40
41// TODO: How should we handle 48 bits?
42
43constexpr std::array VIEW_CLASS_32_BITS = {
44 PixelFormat::RG16F, PixelFormat::R11FG11FB10F, PixelFormat::R32F,
45 PixelFormat::A2B10G10R10U, PixelFormat::RG16UI, PixelFormat::R32UI,
46 PixelFormat::RG16I, PixelFormat::R32I, PixelFormat::ABGR8U,
47 PixelFormat::RG16, PixelFormat::ABGR8S, PixelFormat::RG16S,
48 PixelFormat::RGBA8_SRGB, PixelFormat::E5B9G9R9F, PixelFormat::BGRA8,
49 PixelFormat::BGRA8_SRGB,
50};
51// Missing formats:
52// PixelFormat::RGBA8UI
53// PixelFormat::RGBA8I
54// PixelFormat::RGB10_A2_UI
55
56// TODO: How should we handle 24 bits?
57
58constexpr std::array VIEW_CLASS_16_BITS = {
59 PixelFormat::R16F, PixelFormat::RG8UI, PixelFormat::R16UI, PixelFormat::R16I,
60 PixelFormat::RG8U, PixelFormat::R16U, PixelFormat::RG8S, PixelFormat::R16S,
61};
62// Missing formats:
63// PixelFormat::RG8I
64
65constexpr std::array VIEW_CLASS_8_BITS = {
66 PixelFormat::R8UI,
67 PixelFormat::R8U,
68};
69// Missing formats:
70// PixelFormat::R8I
71// PixelFormat::R8S
72
73constexpr std::array VIEW_CLASS_RGTC1_RED = {
74 PixelFormat::DXN1,
75};
76// Missing formats:
77// COMPRESSED_SIGNED_RED_RGTC1
78
79constexpr std::array VIEW_CLASS_RGTC2_RG = {
80 PixelFormat::DXN2UNORM,
81 PixelFormat::DXN2SNORM,
82};
83
84constexpr std::array VIEW_CLASS_BPTC_UNORM = {
85 PixelFormat::BC7U,
86 PixelFormat::BC7U_SRGB,
87};
88
89constexpr std::array VIEW_CLASS_BPTC_FLOAT = {
90 PixelFormat::BC6H_SF16,
91 PixelFormat::BC6H_UF16,
92};
93
94// Compatibility table taken from Table 4.X.1 in:
95// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_copy_image.txt
96
97constexpr std::array COPY_CLASS_128_BITS = {
98 PixelFormat::RGBA32UI, PixelFormat::RGBA32F, PixelFormat::DXT23,
99 PixelFormat::DXT23_SRGB, PixelFormat::DXT45, PixelFormat::DXT45_SRGB,
100 PixelFormat::DXN2SNORM, PixelFormat::BC7U, PixelFormat::BC7U_SRGB,
101 PixelFormat::BC6H_SF16, PixelFormat::BC6H_UF16,
102};
103// Missing formats:
104// PixelFormat::RGBA32I
105// COMPRESSED_RG_RGTC2
106
107constexpr std::array COPY_CLASS_64_BITS = {
108 PixelFormat::RGBA16F, PixelFormat::RG32F, PixelFormat::RGBA16UI, PixelFormat::RG32UI,
109 PixelFormat::RGBA16U, PixelFormat::RGBA16S, PixelFormat::DXT1_SRGB, PixelFormat::DXT1,
110
111};
112// Missing formats:
113// PixelFormat::RGBA16I
114// PixelFormat::RG32I,
115// COMPRESSED_RGB_S3TC_DXT1_EXT
116// COMPRESSED_SRGB_S3TC_DXT1_EXT
117// COMPRESSED_RGBA_S3TC_DXT1_EXT
118// COMPRESSED_SIGNED_RED_RGTC1
119
120void Enable(FormatCompatibility::Table& compatiblity, size_t format_a, size_t format_b) {
121 compatiblity[format_a][format_b] = true;
122 compatiblity[format_b][format_a] = true;
123}
124
125void Enable(FormatCompatibility::Table& compatibility, PixelFormat format_a, PixelFormat format_b) {
126 Enable(compatibility, static_cast<size_t>(format_a), static_cast<size_t>(format_b));
127}
128
129template <typename Range>
130void EnableRange(FormatCompatibility::Table& compatibility, const Range& range) {
131 for (auto it_a = range.begin(); it_a != range.end(); ++it_a) {
132 for (auto it_b = it_a; it_b != range.end(); ++it_b) {
133 Enable(compatibility, *it_a, *it_b);
134 }
135 }
136}
137
138} // Anonymous namespace
139
140FormatCompatibility::FormatCompatibility() {
141 for (size_t i = 0; i < MaxPixelFormat; ++i) {
142 // Identity is allowed
143 Enable(view, i, i);
144 }
145
146 EnableRange(view, VIEW_CLASS_128_BITS);
147 EnableRange(view, VIEW_CLASS_96_BITS);
148 EnableRange(view, VIEW_CLASS_64_BITS);
149 EnableRange(view, VIEW_CLASS_32_BITS);
150 EnableRange(view, VIEW_CLASS_16_BITS);
151 EnableRange(view, VIEW_CLASS_8_BITS);
152 EnableRange(view, VIEW_CLASS_RGTC1_RED);
153 EnableRange(view, VIEW_CLASS_RGTC2_RG);
154 EnableRange(view, VIEW_CLASS_BPTC_UNORM);
155 EnableRange(view, VIEW_CLASS_BPTC_FLOAT);
156
157 copy = view;
158 EnableRange(copy, COPY_CLASS_128_BITS);
159 EnableRange(copy, COPY_CLASS_64_BITS);
160}
161
162} // namespace VideoCore::Surface
diff --git a/src/video_core/compatible_formats.h b/src/video_core/compatible_formats.h
new file mode 100644
index 000000000..d1082566d
--- /dev/null
+++ b/src/video_core/compatible_formats.h
@@ -0,0 +1,32 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <array>
6#include <bitset>
7#include <cstddef>
8
9#include "video_core/surface.h"
10
11namespace VideoCore::Surface {
12
13class FormatCompatibility {
14public:
15 using Table = std::array<std::bitset<MaxPixelFormat>, MaxPixelFormat>;
16
17 explicit FormatCompatibility();
18
19 bool TestView(PixelFormat format_a, PixelFormat format_b) const noexcept {
20 return view[static_cast<size_t>(format_a)][static_cast<size_t>(format_b)];
21 }
22
23 bool TestCopy(PixelFormat format_a, PixelFormat format_b) const noexcept {
24 return copy[static_cast<size_t>(format_a)][static_cast<size_t>(format_b)];
25 }
26
27private:
28 Table view;
29 Table copy;
30};
31
32} // namespace VideoCore::Surface
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 85075e868..6207d8dfe 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -24,6 +24,7 @@
24#include "core/core.h" 24#include "core/core.h"
25#include "core/memory.h" 25#include "core/memory.h"
26#include "core/settings.h" 26#include "core/settings.h"
27#include "video_core/compatible_formats.h"
27#include "video_core/dirty_flags.h" 28#include "video_core/dirty_flags.h"
28#include "video_core/engines/fermi_2d.h" 29#include "video_core/engines/fermi_2d.h"
29#include "video_core/engines/maxwell_3d.h" 30#include "video_core/engines/maxwell_3d.h"
@@ -47,8 +48,8 @@ class RasterizerInterface;
47 48
48namespace VideoCommon { 49namespace VideoCommon {
49 50
51using VideoCore::Surface::FormatCompatibility;
50using VideoCore::Surface::PixelFormat; 52using VideoCore::Surface::PixelFormat;
51
52using VideoCore::Surface::SurfaceTarget; 53using VideoCore::Surface::SurfaceTarget;
53using RenderTargetConfig = Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig; 54using RenderTargetConfig = Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig;
54 55
@@ -595,7 +596,7 @@ private:
595 } else { 596 } else {
596 new_surface = GetUncachedSurface(gpu_addr, params); 597 new_surface = GetUncachedSurface(gpu_addr, params);
597 } 598 }
598 const auto& final_params = new_surface->GetSurfaceParams(); 599 const SurfaceParams& final_params = new_surface->GetSurfaceParams();
599 if (cr_params.type != final_params.type) { 600 if (cr_params.type != final_params.type) {
600 if (Settings::IsGPULevelExtreme()) { 601 if (Settings::IsGPULevelExtreme()) {
601 BufferCopy(current_surface, new_surface); 602 BufferCopy(current_surface, new_surface);
@@ -603,7 +604,7 @@ private:
603 } else { 604 } else {
604 std::vector<CopyParams> bricks = current_surface->BreakDown(final_params); 605 std::vector<CopyParams> bricks = current_surface->BreakDown(final_params);
605 for (auto& brick : bricks) { 606 for (auto& brick : bricks) {
606 ImageCopy(current_surface, new_surface, brick); 607 TryCopyImage(current_surface, new_surface, brick);
607 } 608 }
608 } 609 }
609 Unregister(current_surface); 610 Unregister(current_surface);
@@ -694,7 +695,7 @@ private:
694 } 695 }
695 const CopyParams copy_params(0, 0, 0, 0, 0, base_layer, 0, mipmap, width, height, 696 const CopyParams copy_params(0, 0, 0, 0, 0, base_layer, 0, mipmap, width, height,
696 src_params.depth); 697 src_params.depth);
697 ImageCopy(surface, new_surface, copy_params); 698 TryCopyImage(surface, new_surface, copy_params);
698 } 699 }
699 } 700 }
700 if (passed_tests == 0) { 701 if (passed_tests == 0) {
@@ -791,7 +792,7 @@ private:
791 const u32 width = params.width; 792 const u32 width = params.width;
792 const u32 height = params.height; 793 const u32 height = params.height;
793 const CopyParams copy_params(0, 0, 0, 0, 0, slice, 0, 0, width, height, 1); 794 const CopyParams copy_params(0, 0, 0, 0, 0, slice, 0, 0, width, height, 1);
794 ImageCopy(surface, new_surface, copy_params); 795 TryCopyImage(surface, new_surface, copy_params);
795 } 796 }
796 for (const auto& surface : overlaps) { 797 for (const auto& surface : overlaps) {
797 Unregister(surface); 798 Unregister(surface);
@@ -1192,6 +1193,19 @@ private:
1192 return {}; 1193 return {};
1193 } 1194 }
1194 1195
1196 /// Try to do an image copy logging when formats are incompatible.
1197 void TryCopyImage(TSurface& src, TSurface& dst, const CopyParams& copy) {
1198 const SurfaceParams& src_params = src->GetSurfaceParams();
1199 const SurfaceParams& dst_params = dst->GetSurfaceParams();
1200 if (!format_compatibility.TestCopy(src_params.pixel_format, dst_params.pixel_format)) {
1201 LOG_ERROR(HW_GPU, "Illegal copy between formats={{{}, {}}}",
1202 static_cast<int>(dst_params.pixel_format),
1203 static_cast<int>(src_params.pixel_format));
1204 return;
1205 }
1206 ImageCopy(src, dst, copy);
1207 }
1208
1195 constexpr PixelFormat GetSiblingFormat(PixelFormat format) const { 1209 constexpr PixelFormat GetSiblingFormat(PixelFormat format) const {
1196 return siblings_table[static_cast<std::size_t>(format)]; 1210 return siblings_table[static_cast<std::size_t>(format)];
1197 } 1211 }
@@ -1241,6 +1255,7 @@ private:
1241 VideoCore::RasterizerInterface& rasterizer; 1255 VideoCore::RasterizerInterface& rasterizer;
1242 1256
1243 FormatLookupTable format_lookup_table; 1257 FormatLookupTable format_lookup_table;
1258 FormatCompatibility format_compatibility;
1244 1259
1245 u64 ticks{}; 1260 u64 ticks{};
1246 1261