summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/file_util.cpp11
-rw-r--r--src/common/file_util.h3
-rw-r--r--src/core/file_sys/mode.h6
-rw-r--r--src/core/file_sys/partition_filesystem.cpp6
-rw-r--r--src/core/file_sys/vfs_real.cpp47
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp45
-rw-r--r--src/video_core/gpu.cpp2
-rw-r--r--src/video_core/gpu.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h56
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp13
-rw-r--r--src/video_core/textures/decoders.cpp4
12 files changed, 158 insertions, 55 deletions
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 1bc291cf9..b8dd92b65 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -826,7 +826,7 @@ std::string_view GetPathWithoutTop(std::string_view path) {
826 } 826 }
827 827
828 while (path[0] == '\\' || path[0] == '/') { 828 while (path[0] == '\\' || path[0] == '/') {
829 path.remove_suffix(1); 829 path.remove_prefix(1);
830 if (path.empty()) { 830 if (path.empty()) {
831 return path; 831 return path;
832 } 832 }
@@ -870,6 +870,15 @@ std::string_view RemoveTrailingSlash(std::string_view path) {
870 return path; 870 return path;
871} 871}
872 872
873std::string SanitizePath(std::string_view path_) {
874 std::string path(path_);
875 std::replace(path.begin(), path.end(), '\\', '/');
876 path.erase(std::unique(path.begin(), path.end(),
877 [](char c1, char c2) { return c1 == '/' && c2 == '/'; }),
878 path.end());
879 return std::string(RemoveTrailingSlash(path));
880}
881
873IOFile::IOFile() {} 882IOFile::IOFile() {}
874 883
875IOFile::IOFile(const std::string& filename, const char openmode[], int flags) { 884IOFile::IOFile(const std::string& filename, const char openmode[], int flags) {
diff --git a/src/common/file_util.h b/src/common/file_util.h
index abfa79eae..bc9272d89 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -178,6 +178,9 @@ std::vector<T> SliceVector(const std::vector<T>& vector, size_t first, size_t la
178 return std::vector<T>(vector.begin() + first, vector.begin() + first + last); 178 return std::vector<T>(vector.begin() + first, vector.begin() + first + last);
179} 179}
180 180
181// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'.
182std::string SanitizePath(std::string_view path);
183
181// simple wrapper for cstdlib file functions to 184// simple wrapper for cstdlib file functions to
182// hopefully will make error checking easier 185// hopefully will make error checking easier
183// and make forgetting an fclose() harder 186// and make forgetting an fclose() harder
diff --git a/src/core/file_sys/mode.h b/src/core/file_sys/mode.h
index b4363152a..c95205668 100644
--- a/src/core/file_sys/mode.h
+++ b/src/core/file_sys/mode.h
@@ -11,7 +11,13 @@ namespace FileSys {
11enum class Mode : u32 { 11enum class Mode : u32 {
12 Read = 1, 12 Read = 1,
13 Write = 2, 13 Write = 2,
14 ReadWrite = 3,
14 Append = 4, 15 Append = 4,
16 WriteAppend = 6,
15}; 17};
16 18
19inline u32 operator&(Mode lhs, Mode rhs) {
20 return static_cast<u32>(lhs) & static_cast<u32>(rhs);
21}
22
17} // namespace FileSys 23} // namespace FileSys
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp
index 8d2bd9f6b..521e21078 100644
--- a/src/core/file_sys/partition_filesystem.cpp
+++ b/src/core/file_sys/partition_filesystem.cpp
@@ -65,8 +65,8 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) {
65 std::string name( 65 std::string name(
66 reinterpret_cast<const char*>(&file_data[strtab_offset + entry.strtab_offset])); 66 reinterpret_cast<const char*>(&file_data[strtab_offset + entry.strtab_offset]));
67 67
68 pfs_files.emplace_back( 68 pfs_files.emplace_back(std::make_shared<OffsetVfsFile>(
69 std::make_shared<OffsetVfsFile>(file, entry.size, content_offset + entry.offset, name)); 69 file, entry.size, content_offset + entry.offset, std::move(name)));
70 } 70 }
71 71
72 status = Loader::ResultStatus::Success; 72 status = Loader::ResultStatus::Success;
@@ -109,7 +109,7 @@ bool PartitionFilesystem::ReplaceFileWithSubdirectory(VirtualFile file, VirtualD
109 return false; 109 return false;
110 110
111 const std::ptrdiff_t offset = std::distance(pfs_files.begin(), iter); 111 const std::ptrdiff_t offset = std::distance(pfs_files.begin(), iter);
112 pfs_files[offset] = pfs_files.back(); 112 pfs_files[offset] = std::move(pfs_files.back());
113 pfs_files.pop_back(); 113 pfs_files.pop_back();
114 114
115 pfs_dirs.emplace_back(std::move(dir)); 115 pfs_dirs.emplace_back(std::move(dir));
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 095fec77e..9ce2e1efa 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -13,24 +13,31 @@
13 13
14namespace FileSys { 14namespace FileSys {
15 15
16static std::string PermissionsToCharArray(Mode perms) { 16static std::string ModeFlagsToString(Mode mode) {
17 std::string out; 17 std::string mode_str;
18 switch (perms) { 18
19 case Mode::Read: 19 // Calculate the correct open mode for the file.
20 out += "r"; 20 if (mode & Mode::Read && mode & Mode::Write) {
21 break; 21 if (mode & Mode::Append)
22 case Mode::Write: 22 mode_str = "a+";
23 out += "r+"; 23 else
24 break; 24 mode_str = "r+";
25 case Mode::Append: 25 } else {
26 out += "a"; 26 if (mode & Mode::Read)
27 break; 27 mode_str = "r";
28 else if (mode & Mode::Append)
29 mode_str = "a";
30 else if (mode & Mode::Write)
31 mode_str = "w";
28 } 32 }
29 return out + "b"; 33
34 mode_str += "b";
35
36 return mode_str;
30} 37}
31 38
32RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_) 39RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_)
33 : backing(path_, PermissionsToCharArray(perms_).c_str()), path(path_), 40 : backing(path_, ModeFlagsToString(perms_).c_str()), path(path_),
34 parent_path(FileUtil::GetParentPath(path_)), 41 parent_path(FileUtil::GetParentPath(path_)),
35 path_components(FileUtil::SplitPathComponents(path_)), 42 path_components(FileUtil::SplitPathComponents(path_)),
36 parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), 43 parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
@@ -53,11 +60,11 @@ std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const {
53} 60}
54 61
55bool RealVfsFile::IsWritable() const { 62bool RealVfsFile::IsWritable() const {
56 return perms == Mode::Append || perms == Mode::Write; 63 return (perms & Mode::WriteAppend) != 0;
57} 64}
58 65
59bool RealVfsFile::IsReadable() const { 66bool RealVfsFile::IsReadable() const {
60 return perms == Mode::Read || perms == Mode::Write; 67 return (perms & Mode::ReadWrite) != 0;
61} 68}
62 69
63size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const { 70size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const {
@@ -79,7 +86,7 @@ bool RealVfsFile::Rename(std::string_view name) {
79 path = (parent_path + DIR_SEP).append(name); 86 path = (parent_path + DIR_SEP).append(name);
80 path_components = parent_components; 87 path_components = parent_components;
81 path_components.push_back(std::move(name_str)); 88 path_components.push_back(std::move(name_str));
82 backing = FileUtil::IOFile(path, PermissionsToCharArray(perms).c_str()); 89 backing = FileUtil::IOFile(path, ModeFlagsToString(perms).c_str());
83 90
84 return out; 91 return out;
85} 92}
@@ -93,7 +100,7 @@ RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_)
93 path_components(FileUtil::SplitPathComponents(path)), 100 path_components(FileUtil::SplitPathComponents(path)),
94 parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), 101 parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
95 perms(perms_) { 102 perms(perms_) {
96 if (!FileUtil::Exists(path) && (perms == Mode::Write || perms == Mode::Append)) 103 if (!FileUtil::Exists(path) && perms & Mode::WriteAppend)
97 FileUtil::CreateDir(path); 104 FileUtil::CreateDir(path);
98 105
99 if (perms == Mode::Append) 106 if (perms == Mode::Append)
@@ -120,11 +127,11 @@ std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories()
120} 127}
121 128
122bool RealVfsDirectory::IsWritable() const { 129bool RealVfsDirectory::IsWritable() const {
123 return perms == Mode::Write || perms == Mode::Append; 130 return (perms & Mode::WriteAppend) != 0;
124} 131}
125 132
126bool RealVfsDirectory::IsReadable() const { 133bool RealVfsDirectory::IsReadable() const {
127 return perms == Mode::Read || perms == Mode::Write; 134 return (perms & Mode::ReadWrite) != 0;
128} 135}
129 136
130std::string RealVfsDirectory::GetName() const { 137std::string RealVfsDirectory::GetName() const {
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index dbfe06cbc..fdd2fda18 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -24,7 +24,8 @@ namespace Service::FileSystem {
24constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000; 24constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
25 25
26static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, 26static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
27 std::string_view dir_name) { 27 std::string_view dir_name_) {
28 std::string dir_name(FileUtil::SanitizePath(dir_name_));
28 if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\") 29 if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\")
29 return base; 30 return base;
30 31
@@ -38,7 +39,8 @@ std::string VfsDirectoryServiceWrapper::GetName() const {
38 return backing->GetName(); 39 return backing->GetName();
39} 40}
40 41
41ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 size) const { 42ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const {
43 std::string path(FileUtil::SanitizePath(path_));
42 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); 44 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
43 auto file = dir->CreateFile(FileUtil::GetFilename(path)); 45 auto file = dir->CreateFile(FileUtil::GetFilename(path));
44 if (file == nullptr) { 46 if (file == nullptr) {
@@ -52,7 +54,8 @@ ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 s
52 return RESULT_SUCCESS; 54 return RESULT_SUCCESS;
53} 55}
54 56
55ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const { 57ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const {
58 std::string path(FileUtil::SanitizePath(path_));
56 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); 59 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
57 if (path == "/" || path == "\\") { 60 if (path == "/" || path == "\\") {
58 // TODO(DarkLordZach): Why do games call this and what should it do? Works as is but... 61 // TODO(DarkLordZach): Why do games call this and what should it do? Works as is but...
@@ -60,14 +63,15 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const
60 } 63 }
61 if (dir->GetFile(FileUtil::GetFilename(path)) == nullptr) 64 if (dir->GetFile(FileUtil::GetFilename(path)) == nullptr)
62 return FileSys::ERROR_PATH_NOT_FOUND; 65 return FileSys::ERROR_PATH_NOT_FOUND;
63 if (!backing->DeleteFile(FileUtil::GetFilename(path))) { 66 if (!dir->DeleteFile(FileUtil::GetFilename(path))) {
64 // TODO(DarkLordZach): Find a better error code for this 67 // TODO(DarkLordZach): Find a better error code for this
65 return ResultCode(-1); 68 return ResultCode(-1);
66 } 69 }
67 return RESULT_SUCCESS; 70 return RESULT_SUCCESS;
68} 71}
69 72
70ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) const { 73ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const {
74 std::string path(FileUtil::SanitizePath(path_));
71 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); 75 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
72 if (dir == nullptr && FileUtil::GetFilename(FileUtil::GetParentPath(path)).empty()) 76 if (dir == nullptr && FileUtil::GetFilename(FileUtil::GetParentPath(path)).empty())
73 dir = backing; 77 dir = backing;
@@ -79,7 +83,8 @@ ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path)
79 return RESULT_SUCCESS; 83 return RESULT_SUCCESS;
80} 84}
81 85
82ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) const { 86ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_) const {
87 std::string path(FileUtil::SanitizePath(path_));
83 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); 88 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
84 if (!dir->DeleteSubdirectory(FileUtil::GetFilename(path))) { 89 if (!dir->DeleteSubdirectory(FileUtil::GetFilename(path))) {
85 // TODO(DarkLordZach): Find a better error code for this 90 // TODO(DarkLordZach): Find a better error code for this
@@ -88,7 +93,8 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path)
88 return RESULT_SUCCESS; 93 return RESULT_SUCCESS;
89} 94}
90 95
91ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path) const { 96ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path_) const {
97 std::string path(FileUtil::SanitizePath(path_));
92 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); 98 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
93 if (!dir->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path))) { 99 if (!dir->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path))) {
94 // TODO(DarkLordZach): Find a better error code for this 100 // TODO(DarkLordZach): Find a better error code for this
@@ -97,8 +103,10 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::str
97 return RESULT_SUCCESS; 103 return RESULT_SUCCESS;
98} 104}
99 105
100ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path, 106ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_,
101 const std::string& dest_path) const { 107 const std::string& dest_path_) const {
108 std::string src_path(FileUtil::SanitizePath(src_path_));
109 std::string dest_path(FileUtil::SanitizePath(dest_path_));
102 auto src = backing->GetFileRelative(src_path); 110 auto src = backing->GetFileRelative(src_path);
103 if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { 111 if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) {
104 // Use more-optimized vfs implementation rename. 112 // Use more-optimized vfs implementation rename.
@@ -130,8 +138,10 @@ ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path,
130 return RESULT_SUCCESS; 138 return RESULT_SUCCESS;
131} 139}
132 140
133ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path, 141ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,
134 const std::string& dest_path) const { 142 const std::string& dest_path_) const {
143 std::string src_path(FileUtil::SanitizePath(src_path_));
144 std::string dest_path(FileUtil::SanitizePath(dest_path_));
135 auto src = GetDirectoryRelativeWrapped(backing, src_path); 145 auto src = GetDirectoryRelativeWrapped(backing, src_path);
136 if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { 146 if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) {
137 // Use more-optimized vfs implementation rename. 147 // Use more-optimized vfs implementation rename.
@@ -154,8 +164,9 @@ ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_pa
154 return ResultCode(-1); 164 return ResultCode(-1);
155} 165}
156 166
157ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path, 167ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_,
158 FileSys::Mode mode) const { 168 FileSys::Mode mode) const {
169 std::string path(FileUtil::SanitizePath(path_));
159 auto npath = path; 170 auto npath = path;
160 while (npath.size() > 0 && (npath[0] == '/' || npath[0] == '\\')) 171 while (npath.size() > 0 && (npath[0] == '/' || npath[0] == '\\'))
161 npath = npath.substr(1); 172 npath = npath.substr(1);
@@ -171,7 +182,8 @@ ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::
171 return MakeResult<FileSys::VirtualFile>(file); 182 return MakeResult<FileSys::VirtualFile>(file);
172} 183}
173 184
174ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) { 185ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) {
186 std::string path(FileUtil::SanitizePath(path_));
175 auto dir = GetDirectoryRelativeWrapped(backing, path); 187 auto dir = GetDirectoryRelativeWrapped(backing, path);
176 if (dir == nullptr) { 188 if (dir == nullptr) {
177 // TODO(DarkLordZach): Find a better error code for this 189 // TODO(DarkLordZach): Find a better error code for this
@@ -188,7 +200,8 @@ u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const {
188} 200}
189 201
190ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( 202ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
191 const std::string& path) const { 203 const std::string& path_) const {
204 std::string path(FileUtil::SanitizePath(path_));
192 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); 205 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
193 if (dir == nullptr) 206 if (dir == nullptr)
194 return FileSys::ERROR_PATH_NOT_FOUND; 207 return FileSys::ERROR_PATH_NOT_FOUND;
@@ -272,9 +285,9 @@ void RegisterFileSystems() {
272 sdmc_factory = nullptr; 285 sdmc_factory = nullptr;
273 286
274 auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>( 287 auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>(
275 FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::Write); 288 FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::ReadWrite);
276 auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>( 289 auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>(
277 FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::Write); 290 FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::ReadWrite);
278 291
279 auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory)); 292 auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
280 save_data_factory = std::move(savedata); 293 save_data_factory = std::move(savedata);
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index a003bc9e3..60c49d672 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -35,9 +35,11 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
35 case RenderTargetFormat::RGBA32_FLOAT: 35 case RenderTargetFormat::RGBA32_FLOAT:
36 return 16; 36 return 16;
37 case RenderTargetFormat::RGBA16_FLOAT: 37 case RenderTargetFormat::RGBA16_FLOAT:
38 case RenderTargetFormat::RG32_FLOAT:
38 return 8; 39 return 8;
39 case RenderTargetFormat::RGBA8_UNORM: 40 case RenderTargetFormat::RGBA8_UNORM:
40 case RenderTargetFormat::RGB10_A2_UNORM: 41 case RenderTargetFormat::RGB10_A2_UNORM:
42 case RenderTargetFormat::BGRA8_UNORM:
41 return 4; 43 return 4;
42 default: 44 default:
43 UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format)); 45 UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format));
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index a32148ecd..58501ca8b 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -18,6 +18,8 @@ enum class RenderTargetFormat : u32 {
18 RGBA32_FLOAT = 0xC0, 18 RGBA32_FLOAT = 0xC0,
19 RGBA32_UINT = 0xC2, 19 RGBA32_UINT = 0xC2,
20 RGBA16_FLOAT = 0xCA, 20 RGBA16_FLOAT = 0xCA,
21 RG32_FLOAT = 0xCB,
22 BGRA8_UNORM = 0xCF,
21 RGB10_A2_UNORM = 0xD1, 23 RGB10_A2_UNORM = 0xD1,
22 RGBA8_UNORM = 0xD5, 24 RGBA8_UNORM = 0xD5,
23 RGBA8_SRGB = 0xD6, 25 RGBA8_SRGB = 0xD6,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 28f0bc379..8f99864a0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -38,7 +38,8 @@ struct FormatTuple {
38 params.addr = config.tic.Address(); 38 params.addr = config.tic.Address();
39 params.is_tiled = config.tic.IsTiled(); 39 params.is_tiled = config.tic.IsTiled();
40 params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0, 40 params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0,
41 params.pixel_format = PixelFormatFromTextureFormat(config.tic.format); 41 params.pixel_format =
42 PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value());
42 params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); 43 params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value());
43 params.type = GetFormatType(params.pixel_format); 44 params.type = GetFormatType(params.pixel_format);
44 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); 45 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
@@ -106,6 +107,9 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
106 true}, // BC7U 107 true}, // BC7U
107 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4 108 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4
108 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8 109 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8
110 {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8
111 {GL_RGBA32F, GL_RGBA, GL_FLOAT, ComponentType::Float, false}, // RGBA32F
112 {GL_RG32F, GL_RG, GL_FLOAT, ComponentType::Float, false}, // RG32F
109 113
110 // DepthStencil formats 114 // DepthStencil formats
111 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, 115 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm,
@@ -197,9 +201,10 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
197 MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>, 201 MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
198 MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>, 202 MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>,
199 MortonCopy<true, PixelFormat::BC7U>, MortonCopy<true, PixelFormat::ASTC_2D_4X4>, 203 MortonCopy<true, PixelFormat::BC7U>, MortonCopy<true, PixelFormat::ASTC_2D_4X4>,
200 MortonCopy<true, PixelFormat::G8R8>, MortonCopy<true, PixelFormat::Z24S8>, 204 MortonCopy<true, PixelFormat::G8R8>, MortonCopy<true, PixelFormat::BGRA8>,
201 MortonCopy<true, PixelFormat::S8Z24>, MortonCopy<true, PixelFormat::Z32F>, 205 MortonCopy<true, PixelFormat::RGBA32F>, MortonCopy<true, PixelFormat::RG32F>,
202 MortonCopy<true, PixelFormat::Z16>, 206 MortonCopy<true, PixelFormat::Z24S8>, MortonCopy<true, PixelFormat::S8Z24>,
207 MortonCopy<true, PixelFormat::Z32F>, MortonCopy<true, PixelFormat::Z16>,
203}; 208};
204 209
205static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), 210static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
@@ -213,7 +218,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
213 MortonCopy<false, PixelFormat::RGBA16F>, 218 MortonCopy<false, PixelFormat::RGBA16F>,
214 MortonCopy<false, PixelFormat::R11FG11FB10F>, 219 MortonCopy<false, PixelFormat::R11FG11FB10F>,
215 MortonCopy<false, PixelFormat::RGBA32UI>, 220 MortonCopy<false, PixelFormat::RGBA32UI>,
216 // TODO(Subv): Swizzling the DXT1/DXT23/DXT45/DXN1/BC7U formats is not yet supported 221 // TODO(Subv): Swizzling DXT1/DXT23/DXT45/DXN1/BC7U/ASTC_2D_4X4 formats is not supported
217 nullptr, 222 nullptr,
218 nullptr, 223 nullptr,
219 nullptr, 224 nullptr,
@@ -221,6 +226,9 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
221 nullptr, 226 nullptr,
222 nullptr, 227 nullptr,
223 MortonCopy<false, PixelFormat::G8R8>, 228 MortonCopy<false, PixelFormat::G8R8>,
229 MortonCopy<false, PixelFormat::BGRA8>,
230 MortonCopy<false, PixelFormat::RGBA32F>,
231 MortonCopy<false, PixelFormat::RG32F>,
224 MortonCopy<false, PixelFormat::Z24S8>, 232 MortonCopy<false, PixelFormat::Z24S8>,
225 MortonCopy<false, PixelFormat::S8Z24>, 233 MortonCopy<false, PixelFormat::S8Z24>,
226 MortonCopy<false, PixelFormat::Z32F>, 234 MortonCopy<false, PixelFormat::Z32F>,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index b084c4db4..23efbe67c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -37,14 +37,17 @@ struct SurfaceParams {
37 BC7U = 12, 37 BC7U = 12,
38 ASTC_2D_4X4 = 13, 38 ASTC_2D_4X4 = 13,
39 G8R8 = 14, 39 G8R8 = 14,
40 BGRA8 = 15,
41 RGBA32F = 16,
42 RG32F = 17,
40 43
41 MaxColorFormat, 44 MaxColorFormat,
42 45
43 // DepthStencil formats 46 // DepthStencil formats
44 Z24S8 = 15, 47 Z24S8 = 18,
45 S8Z24 = 16, 48 S8Z24 = 19,
46 Z32F = 17, 49 Z32F = 20,
47 Z16 = 18, 50 Z16 = 21,
48 51
49 MaxDepthStencilFormat, 52 MaxDepthStencilFormat,
50 53
@@ -97,6 +100,9 @@ struct SurfaceParams {
97 4, // BC7U 100 4, // BC7U
98 4, // ASTC_2D_4X4 101 4, // ASTC_2D_4X4
99 1, // G8R8 102 1, // G8R8
103 1, // BGRA8
104 1, // RGBA32F
105 1, // RG32F
100 1, // Z24S8 106 1, // Z24S8
101 1, // S8Z24 107 1, // S8Z24
102 1, // Z32F 108 1, // Z32F
@@ -127,6 +133,9 @@ struct SurfaceParams {
127 128, // BC7U 133 128, // BC7U
128 32, // ASTC_2D_4X4 134 32, // ASTC_2D_4X4
129 16, // G8R8 135 16, // G8R8
136 32, // BGRA8
137 128, // RGBA32F
138 64, // RG32F
130 32, // Z24S8 139 32, // Z24S8
131 32, // S8Z24 140 32, // S8Z24
132 32, // Z32F 141 32, // Z32F
@@ -162,10 +171,16 @@ struct SurfaceParams {
162 case Tegra::RenderTargetFormat::RGBA8_UNORM: 171 case Tegra::RenderTargetFormat::RGBA8_UNORM:
163 case Tegra::RenderTargetFormat::RGBA8_SRGB: 172 case Tegra::RenderTargetFormat::RGBA8_SRGB:
164 return PixelFormat::ABGR8; 173 return PixelFormat::ABGR8;
174 case Tegra::RenderTargetFormat::BGRA8_UNORM:
175 return PixelFormat::BGRA8;
165 case Tegra::RenderTargetFormat::RGB10_A2_UNORM: 176 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
166 return PixelFormat::A2B10G10R10; 177 return PixelFormat::A2B10G10R10;
167 case Tegra::RenderTargetFormat::RGBA16_FLOAT: 178 case Tegra::RenderTargetFormat::RGBA16_FLOAT:
168 return PixelFormat::RGBA16F; 179 return PixelFormat::RGBA16F;
180 case Tegra::RenderTargetFormat::RGBA32_FLOAT:
181 return PixelFormat::RGBA32F;
182 case Tegra::RenderTargetFormat::RG32_FLOAT:
183 return PixelFormat::RG32F;
169 case Tegra::RenderTargetFormat::R11G11B10_FLOAT: 184 case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
170 return PixelFormat::R11FG11FB10F; 185 return PixelFormat::R11FG11FB10F;
171 case Tegra::RenderTargetFormat::RGBA32_UINT: 186 case Tegra::RenderTargetFormat::RGBA32_UINT:
@@ -176,7 +191,8 @@ struct SurfaceParams {
176 } 191 }
177 } 192 }
178 193
179 static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format) { 194 static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
195 Tegra::Texture::ComponentType component_type) {
180 // TODO(Subv): Properly implement this 196 // TODO(Subv): Properly implement this
181 switch (format) { 197 switch (format) {
182 case Tegra::Texture::TextureFormat::A8R8G8B8: 198 case Tegra::Texture::TextureFormat::A8R8G8B8:
@@ -196,7 +212,17 @@ struct SurfaceParams {
196 case Tegra::Texture::TextureFormat::BF10GF11RF11: 212 case Tegra::Texture::TextureFormat::BF10GF11RF11:
197 return PixelFormat::R11FG11FB10F; 213 return PixelFormat::R11FG11FB10F;
198 case Tegra::Texture::TextureFormat::R32_G32_B32_A32: 214 case Tegra::Texture::TextureFormat::R32_G32_B32_A32:
199 return PixelFormat::RGBA32UI; 215 switch (component_type) {
216 case Tegra::Texture::ComponentType::FLOAT:
217 return PixelFormat::RGBA32F;
218 case Tegra::Texture::ComponentType::UINT:
219 return PixelFormat::RGBA32UI;
220 }
221 LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
222 static_cast<u32>(component_type));
223 UNREACHABLE();
224 case Tegra::Texture::TextureFormat::R32_G32:
225 return PixelFormat::RG32F;
200 case Tegra::Texture::TextureFormat::DXT1: 226 case Tegra::Texture::TextureFormat::DXT1:
201 return PixelFormat::DXT1; 227 return PixelFormat::DXT1;
202 case Tegra::Texture::TextureFormat::DXT23: 228 case Tegra::Texture::TextureFormat::DXT23:
@@ -210,7 +236,8 @@ struct SurfaceParams {
210 case Tegra::Texture::TextureFormat::ASTC_2D_4X4: 236 case Tegra::Texture::TextureFormat::ASTC_2D_4X4:
211 return PixelFormat::ASTC_2D_4X4; 237 return PixelFormat::ASTC_2D_4X4;
212 default: 238 default:
213 LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 239 LOG_CRITICAL(HW_GPU, "Unimplemented format={}, component_type={}",
240 static_cast<u32>(format), static_cast<u32>(component_type));
214 UNREACHABLE(); 241 UNREACHABLE();
215 } 242 }
216 } 243 }
@@ -248,7 +275,16 @@ struct SurfaceParams {
248 return Tegra::Texture::TextureFormat::BC7U; 275 return Tegra::Texture::TextureFormat::BC7U;
249 case PixelFormat::ASTC_2D_4X4: 276 case PixelFormat::ASTC_2D_4X4:
250 return Tegra::Texture::TextureFormat::ASTC_2D_4X4; 277 return Tegra::Texture::TextureFormat::ASTC_2D_4X4;
278 case PixelFormat::BGRA8:
279 // TODO(bunnei): This is fine for unswizzling (since we just need the right component
280 // sizes), but could be a bug if we used this function in different ways.
281 return Tegra::Texture::TextureFormat::A8R8G8B8;
282 case PixelFormat::RGBA32F:
283 return Tegra::Texture::TextureFormat::R32_G32_B32_A32;
284 case PixelFormat::RG32F:
285 return Tegra::Texture::TextureFormat::R32_G32;
251 default: 286 default:
287 LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
252 UNREACHABLE(); 288 UNREACHABLE();
253 } 289 }
254 } 290 }
@@ -264,6 +300,7 @@ struct SurfaceParams {
264 case PixelFormat::Z16: 300 case PixelFormat::Z16:
265 return Tegra::DepthFormat::Z16_UNORM; 301 return Tegra::DepthFormat::Z16_UNORM;
266 default: 302 default:
303 LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
267 UNREACHABLE(); 304 UNREACHABLE();
268 } 305 }
269 } 306 }
@@ -273,6 +310,8 @@ struct SurfaceParams {
273 switch (type) { 310 switch (type) {
274 case Tegra::Texture::ComponentType::UNORM: 311 case Tegra::Texture::ComponentType::UNORM:
275 return ComponentType::UNorm; 312 return ComponentType::UNorm;
313 case Tegra::Texture::ComponentType::FLOAT:
314 return ComponentType::Float;
276 default: 315 default:
277 LOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type)); 316 LOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type));
278 UNREACHABLE(); 317 UNREACHABLE();
@@ -284,10 +323,13 @@ struct SurfaceParams {
284 switch (format) { 323 switch (format) {
285 case Tegra::RenderTargetFormat::RGBA8_UNORM: 324 case Tegra::RenderTargetFormat::RGBA8_UNORM:
286 case Tegra::RenderTargetFormat::RGBA8_SRGB: 325 case Tegra::RenderTargetFormat::RGBA8_SRGB:
326 case Tegra::RenderTargetFormat::BGRA8_UNORM:
287 case Tegra::RenderTargetFormat::RGB10_A2_UNORM: 327 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
288 return ComponentType::UNorm; 328 return ComponentType::UNorm;
289 case Tegra::RenderTargetFormat::RGBA16_FLOAT: 329 case Tegra::RenderTargetFormat::RGBA16_FLOAT:
290 case Tegra::RenderTargetFormat::R11G11B10_FLOAT: 330 case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
331 case Tegra::RenderTargetFormat::RGBA32_FLOAT:
332 case Tegra::RenderTargetFormat::RG32_FLOAT:
291 return ComponentType::Float; 333 return ComponentType::Float;
292 case Tegra::RenderTargetFormat::RGBA32_UINT: 334 case Tegra::RenderTargetFormat::RGBA32_UINT:
293 return ComponentType::UInt; 335 return ComponentType::UInt;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 4e36b6de8..acf067050 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -488,6 +488,12 @@ private:
488 */ 488 */
489 void SetRegister(const Register& reg, u64 elem, const std::string& value, 489 void SetRegister(const Register& reg, u64 elem, const std::string& value,
490 u64 dest_num_components, u64 value_num_components, u64 dest_elem) { 490 u64 dest_num_components, u64 value_num_components, u64 dest_elem) {
491 if (reg == Register::ZeroIndex) {
492 LOG_CRITICAL(HW_GPU, "Cannot set Register::ZeroIndex");
493 UNREACHABLE();
494 return;
495 }
496
491 std::string dest = GetRegister(reg, static_cast<u32>(dest_elem)); 497 std::string dest = GetRegister(reg, static_cast<u32>(dest_elem));
492 if (dest_num_components > 1) { 498 if (dest_num_components > 1) {
493 dest += GetSwizzle(elem); 499 dest += GetSwizzle(elem);
@@ -750,8 +756,8 @@ private:
750 } 756 }
751 } 757 }
752 758
753 std::string WriteTexsInstruction(const Instruction& instr, const std::string& coord, 759 void WriteTexsInstruction(const Instruction& instr, const std::string& coord,
754 const std::string& texture) { 760 const std::string& texture) {
755 // Add an extra scope and declare the texture coords inside to prevent 761 // Add an extra scope and declare the texture coords inside to prevent
756 // overwriting them in case they are used as outputs of the texs instruction. 762 // overwriting them in case they are used as outputs of the texs instruction.
757 shader.AddLine('{'); 763 shader.AddLine('{');
@@ -804,7 +810,8 @@ private:
804 return offset + 1; 810 return offset + 1;
805 } 811 }
806 812
807 shader.AddLine("// " + std::to_string(offset) + ": " + opcode->GetName()); 813 shader.AddLine("// " + std::to_string(offset) + ": " + opcode->GetName() + " (" +
814 std::to_string(instr.value) + ')');
808 815
809 using Tegra::Shader::Pred; 816 using Tegra::Shader::Pred;
810 ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute, 817 ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index a3e67d105..e5e9e1898 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -72,6 +72,8 @@ u32 BytesPerPixel(TextureFormat format) {
72 return 8; 72 return 8;
73 case TextureFormat::R32_G32_B32_A32: 73 case TextureFormat::R32_G32_B32_A32:
74 return 16; 74 return 16;
75 case TextureFormat::R32_G32:
76 return 8;
75 default: 77 default:
76 UNIMPLEMENTED_MSG("Format not implemented"); 78 UNIMPLEMENTED_MSG("Format not implemented");
77 break; 79 break;
@@ -118,6 +120,7 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
118 case TextureFormat::G8R8: 120 case TextureFormat::G8R8:
119 case TextureFormat::R16_G16_B16_A16: 121 case TextureFormat::R16_G16_B16_A16:
120 case TextureFormat::R32_G32_B32_A32: 122 case TextureFormat::R32_G32_B32_A32:
123 case TextureFormat::R32_G32:
121 case TextureFormat::BF10GF11RF11: 124 case TextureFormat::BF10GF11RF11:
122 case TextureFormat::ASTC_2D_4X4: 125 case TextureFormat::ASTC_2D_4X4:
123 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, 126 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
@@ -174,6 +177,7 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
174 case TextureFormat::G8R8: 177 case TextureFormat::G8R8:
175 case TextureFormat::BF10GF11RF11: 178 case TextureFormat::BF10GF11RF11:
176 case TextureFormat::R32_G32_B32_A32: 179 case TextureFormat::R32_G32_B32_A32:
180 case TextureFormat::R32_G32:
177 // TODO(Subv): For the time being just forward the same data without any decoding. 181 // TODO(Subv): For the time being just forward the same data without any decoding.
178 rgba_data = texture_data; 182 rgba_data = texture_data;
179 break; 183 break;