diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file_sys/vfs_real.cpp | 187 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.h | 30 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 8 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache_base.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.cpp | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.cpp | 30 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.h | 6 |
8 files changed, 153 insertions, 136 deletions
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index cc0076238..7a15d8438 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp | |||
| @@ -25,6 +25,8 @@ namespace FS = Common::FS; | |||
| 25 | 25 | ||
| 26 | namespace { | 26 | namespace { |
| 27 | 27 | ||
| 28 | constexpr size_t MaxOpenFiles = 512; | ||
| 29 | |||
| 28 | constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) { | 30 | constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) { |
| 29 | switch (mode) { | 31 | switch (mode) { |
| 30 | case Mode::Read: | 32 | case Mode::Read: |
| @@ -73,28 +75,30 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const { | |||
| 73 | VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { | 75 | VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { |
| 74 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); | 76 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 75 | 77 | ||
| 76 | if (const auto weak_iter = cache.find(path); weak_iter != cache.cend()) { | 78 | if (auto it = cache.find(path); it != cache.end()) { |
| 77 | const auto& weak = weak_iter->second; | 79 | if (auto file = it->second.lock(); file) { |
| 78 | 80 | return file; | |
| 79 | if (!weak.expired()) { | ||
| 80 | return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms)); | ||
| 81 | } | 81 | } |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | auto backing = FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile); | 84 | if (!FS::Exists(path) || !FS::IsFile(path)) { |
| 85 | |||
| 86 | if (!backing) { | ||
| 87 | return nullptr; | 85 | return nullptr; |
| 88 | } | 86 | } |
| 89 | 87 | ||
| 90 | cache.insert_or_assign(path, std::move(backing)); | 88 | auto reference = std::make_unique<FileReference>(); |
| 89 | this->InsertReferenceIntoList(*reference); | ||
| 91 | 90 | ||
| 92 | // Cannot use make_shared as RealVfsFile constructor is private | 91 | auto file = |
| 93 | return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms)); | 92 | std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, std::move(reference), path, perms)); |
| 93 | cache[path] = file; | ||
| 94 | |||
| 95 | return file; | ||
| 94 | } | 96 | } |
| 95 | 97 | ||
| 96 | VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { | 98 | VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { |
| 97 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); | 99 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 100 | cache.erase(path); | ||
| 101 | |||
| 98 | // Current usages of CreateFile expect to delete the contents of an existing file. | 102 | // Current usages of CreateFile expect to delete the contents of an existing file. |
| 99 | if (FS::IsFile(path)) { | 103 | if (FS::IsFile(path)) { |
| 100 | FS::IOFile temp{path, FS::FileAccessMode::Write, FS::FileType::BinaryFile}; | 104 | FS::IOFile temp{path, FS::FileAccessMode::Write, FS::FileType::BinaryFile}; |
| @@ -123,51 +127,22 @@ VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_ | |||
| 123 | VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { | 127 | VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { |
| 124 | const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); | 128 | const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); |
| 125 | const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); | 129 | const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); |
| 126 | const auto cached_file_iter = cache.find(old_path); | 130 | cache.erase(old_path); |
| 127 | 131 | cache.erase(new_path); | |
| 128 | if (cached_file_iter != cache.cend()) { | 132 | if (!FS::RenameFile(old_path, new_path)) { |
| 129 | auto file = cached_file_iter->second.lock(); | ||
| 130 | |||
| 131 | if (!cached_file_iter->second.expired()) { | ||
| 132 | file->Close(); | ||
| 133 | } | ||
| 134 | |||
| 135 | if (!FS::RenameFile(old_path, new_path)) { | ||
| 136 | return nullptr; | ||
| 137 | } | ||
| 138 | |||
| 139 | cache.erase(old_path); | ||
| 140 | file->Open(new_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile); | ||
| 141 | if (file->IsOpen()) { | ||
| 142 | cache.insert_or_assign(new_path, std::move(file)); | ||
| 143 | } else { | ||
| 144 | LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", new_path); | ||
| 145 | } | ||
| 146 | } else { | ||
| 147 | ASSERT(false); | ||
| 148 | return nullptr; | 133 | return nullptr; |
| 149 | } | 134 | } |
| 150 | |||
| 151 | return OpenFile(new_path, Mode::ReadWrite); | 135 | return OpenFile(new_path, Mode::ReadWrite); |
| 152 | } | 136 | } |
| 153 | 137 | ||
| 154 | bool RealVfsFilesystem::DeleteFile(std::string_view path_) { | 138 | bool RealVfsFilesystem::DeleteFile(std::string_view path_) { |
| 155 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); | 139 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 156 | const auto cached_iter = cache.find(path); | 140 | cache.erase(path); |
| 157 | |||
| 158 | if (cached_iter != cache.cend()) { | ||
| 159 | if (!cached_iter->second.expired()) { | ||
| 160 | cached_iter->second.lock()->Close(); | ||
| 161 | } | ||
| 162 | cache.erase(path); | ||
| 163 | } | ||
| 164 | |||
| 165 | return FS::RemoveFile(path); | 141 | return FS::RemoveFile(path); |
| 166 | } | 142 | } |
| 167 | 143 | ||
| 168 | VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { | 144 | VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { |
| 169 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); | 145 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 170 | // Cannot use make_shared as RealVfsDirectory constructor is private | ||
| 171 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); | 146 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); |
| 172 | } | 147 | } |
| 173 | 148 | ||
| @@ -176,7 +151,6 @@ VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms | |||
| 176 | if (!FS::CreateDirs(path)) { | 151 | if (!FS::CreateDirs(path)) { |
| 177 | return nullptr; | 152 | return nullptr; |
| 178 | } | 153 | } |
| 179 | // Cannot use make_shared as RealVfsDirectory constructor is private | ||
| 180 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); | 154 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); |
| 181 | } | 155 | } |
| 182 | 156 | ||
| @@ -194,73 +168,102 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_, | |||
| 194 | if (!FS::RenameDir(old_path, new_path)) { | 168 | if (!FS::RenameDir(old_path, new_path)) { |
| 195 | return nullptr; | 169 | return nullptr; |
| 196 | } | 170 | } |
| 171 | return OpenDirectory(new_path, Mode::ReadWrite); | ||
| 172 | } | ||
| 197 | 173 | ||
| 198 | for (auto& kv : cache) { | 174 | bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { |
| 199 | // If the path in the cache doesn't start with old_path, then bail on this file. | 175 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 200 | if (kv.first.rfind(old_path, 0) != 0) { | 176 | return FS::RemoveDirRecursively(path); |
| 201 | continue; | 177 | } |
| 202 | } | ||
| 203 | 178 | ||
| 204 | const auto file_old_path = | 179 | void RealVfsFilesystem::RefreshReference(const std::string& path, Mode perms, |
| 205 | FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault); | 180 | FileReference& reference) { |
| 206 | auto file_new_path = FS::SanitizePath(new_path + '/' + kv.first.substr(old_path.size()), | 181 | // Temporarily remove from list. |
| 207 | FS::DirectorySeparator::PlatformDefault); | 182 | this->RemoveReferenceFromList(reference); |
| 208 | const auto& cached = cache[file_old_path]; | ||
| 209 | 183 | ||
| 210 | if (cached.expired()) { | 184 | // Restore file if needed. |
| 211 | continue; | 185 | if (!reference.file) { |
| 212 | } | 186 | this->EvictSingleReference(); |
| 213 | 187 | ||
| 214 | auto file = cached.lock(); | 188 | reference.file = |
| 215 | cache.erase(file_old_path); | 189 | FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile); |
| 216 | file->Open(file_new_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile); | 190 | if (reference.file) { |
| 217 | if (file->IsOpen()) { | 191 | num_open_files++; |
| 218 | cache.insert_or_assign(std::move(file_new_path), std::move(file)); | ||
| 219 | } else { | ||
| 220 | LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", file_new_path); | ||
| 221 | } | 192 | } |
| 222 | } | 193 | } |
| 223 | 194 | ||
| 224 | return OpenDirectory(new_path, Mode::ReadWrite); | 195 | // Reinsert into list. |
| 196 | this->InsertReferenceIntoList(reference); | ||
| 225 | } | 197 | } |
| 226 | 198 | ||
| 227 | bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { | 199 | void RealVfsFilesystem::DropReference(std::unique_ptr<FileReference>&& reference) { |
| 228 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); | 200 | // Remove from list. |
| 201 | this->RemoveReferenceFromList(*reference); | ||
| 229 | 202 | ||
| 230 | for (auto& kv : cache) { | 203 | // Close the file. |
| 231 | // If the path in the cache doesn't start with path, then bail on this file. | 204 | if (reference->file) { |
| 232 | if (kv.first.rfind(path, 0) != 0) { | 205 | reference->file.reset(); |
| 233 | continue; | 206 | num_open_files--; |
| 234 | } | 207 | } |
| 208 | } | ||
| 235 | 209 | ||
| 236 | const auto& entry = cache[kv.first]; | 210 | void RealVfsFilesystem::EvictSingleReference() { |
| 237 | if (!entry.expired()) { | 211 | if (num_open_files < MaxOpenFiles || open_references.empty()) { |
| 238 | entry.lock()->Close(); | 212 | return; |
| 239 | } | 213 | } |
| 214 | |||
| 215 | // Get and remove from list. | ||
| 216 | auto& reference = open_references.back(); | ||
| 217 | this->RemoveReferenceFromList(reference); | ||
| 240 | 218 | ||
| 241 | cache.erase(kv.first); | 219 | // Close the file. |
| 220 | if (reference.file) { | ||
| 221 | reference.file.reset(); | ||
| 222 | num_open_files--; | ||
| 242 | } | 223 | } |
| 243 | 224 | ||
| 244 | return FS::RemoveDirRecursively(path); | 225 | // Reinsert into closed list. |
| 226 | this->InsertReferenceIntoList(reference); | ||
| 227 | } | ||
| 228 | |||
| 229 | void RealVfsFilesystem::InsertReferenceIntoList(FileReference& reference) { | ||
| 230 | if (reference.file) { | ||
| 231 | open_references.push_front(reference); | ||
| 232 | } else { | ||
| 233 | closed_references.push_front(reference); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | void RealVfsFilesystem::RemoveReferenceFromList(FileReference& reference) { | ||
| 238 | if (reference.file) { | ||
| 239 | open_references.erase(open_references.iterator_to(reference)); | ||
| 240 | } else { | ||
| 241 | closed_references.erase(closed_references.iterator_to(reference)); | ||
| 242 | } | ||
| 245 | } | 243 | } |
| 246 | 244 | ||
| 247 | RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FS::IOFile> backing_, | 245 | RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, |
| 248 | const std::string& path_, Mode perms_) | 246 | const std::string& path_, Mode perms_) |
| 249 | : base(base_), backing(std::move(backing_)), path(path_), parent_path(FS::GetParentPath(path_)), | 247 | : base(base_), reference(std::move(reference_)), path(path_), |
| 250 | path_components(FS::SplitPathComponents(path_)), perms(perms_) {} | 248 | parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), |
| 249 | perms(perms_) {} | ||
| 251 | 250 | ||
| 252 | RealVfsFile::~RealVfsFile() = default; | 251 | RealVfsFile::~RealVfsFile() { |
| 252 | base.DropReference(std::move(reference)); | ||
| 253 | } | ||
| 253 | 254 | ||
| 254 | std::string RealVfsFile::GetName() const { | 255 | std::string RealVfsFile::GetName() const { |
| 255 | return path_components.back(); | 256 | return path_components.back(); |
| 256 | } | 257 | } |
| 257 | 258 | ||
| 258 | std::size_t RealVfsFile::GetSize() const { | 259 | std::size_t RealVfsFile::GetSize() const { |
| 259 | return backing->GetSize(); | 260 | base.RefreshReference(path, perms, *reference); |
| 261 | return reference->file ? reference->file->GetSize() : 0; | ||
| 260 | } | 262 | } |
| 261 | 263 | ||
| 262 | bool RealVfsFile::Resize(std::size_t new_size) { | 264 | bool RealVfsFile::Resize(std::size_t new_size) { |
| 263 | return backing->SetSize(new_size); | 265 | base.RefreshReference(path, perms, *reference); |
| 266 | return reference->file ? reference->file->SetSize(new_size) : false; | ||
| 264 | } | 267 | } |
| 265 | 268 | ||
| 266 | VirtualDir RealVfsFile::GetContainingDirectory() const { | 269 | VirtualDir RealVfsFile::GetContainingDirectory() const { |
| @@ -276,27 +279,25 @@ bool RealVfsFile::IsReadable() const { | |||
| 276 | } | 279 | } |
| 277 | 280 | ||
| 278 | std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { | 281 | std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { |
| 279 | if (!backing->Seek(static_cast<s64>(offset))) { | 282 | base.RefreshReference(path, perms, *reference); |
| 283 | if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { | ||
| 280 | return 0; | 284 | return 0; |
| 281 | } | 285 | } |
| 282 | return backing->ReadSpan(std::span{data, length}); | 286 | return reference->file->ReadSpan(std::span{data, length}); |
| 283 | } | 287 | } |
| 284 | 288 | ||
| 285 | std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { | 289 | std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { |
| 286 | if (!backing->Seek(static_cast<s64>(offset))) { | 290 | base.RefreshReference(path, perms, *reference); |
| 291 | if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) { | ||
| 287 | return 0; | 292 | return 0; |
| 288 | } | 293 | } |
| 289 | return backing->WriteSpan(std::span{data, length}); | 294 | return reference->file->WriteSpan(std::span{data, length}); |
| 290 | } | 295 | } |
| 291 | 296 | ||
| 292 | bool RealVfsFile::Rename(std::string_view name) { | 297 | bool RealVfsFile::Rename(std::string_view name) { |
| 293 | return base.MoveFile(path, parent_path + '/' + std::string(name)) != nullptr; | 298 | return base.MoveFile(path, parent_path + '/' + std::string(name)) != nullptr; |
| 294 | } | 299 | } |
| 295 | 300 | ||
| 296 | void RealVfsFile::Close() { | ||
| 297 | backing->Close(); | ||
| 298 | } | ||
| 299 | |||
| 300 | // TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if | 301 | // TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if |
| 301 | // constexpr' because there is a compile error in the branch not used. | 302 | // constexpr' because there is a compile error in the branch not used. |
| 302 | 303 | ||
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index b92c84316..d8c900e33 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h | |||
| @@ -3,8 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <map> | ||
| 6 | #include <string_view> | 7 | #include <string_view> |
| 7 | #include <boost/container/flat_map.hpp> | 8 | #include "common/intrusive_list.h" |
| 8 | #include "core/file_sys/mode.h" | 9 | #include "core/file_sys/mode.h" |
| 9 | #include "core/file_sys/vfs.h" | 10 | #include "core/file_sys/vfs.h" |
| 10 | 11 | ||
| @@ -14,6 +15,11 @@ class IOFile; | |||
| 14 | 15 | ||
| 15 | namespace FileSys { | 16 | namespace FileSys { |
| 16 | 17 | ||
| 18 | struct FileReference : public Common::IntrusiveListBaseNode<FileReference> { | ||
| 19 | std::shared_ptr<Common::FS::IOFile> file{}; | ||
| 20 | }; | ||
| 21 | |||
| 22 | class RealVfsFile; | ||
| 17 | class RealVfsFilesystem : public VfsFilesystem { | 23 | class RealVfsFilesystem : public VfsFilesystem { |
| 18 | public: | 24 | public: |
| 19 | RealVfsFilesystem(); | 25 | RealVfsFilesystem(); |
| @@ -35,7 +41,21 @@ public: | |||
| 35 | bool DeleteDirectory(std::string_view path) override; | 41 | bool DeleteDirectory(std::string_view path) override; |
| 36 | 42 | ||
| 37 | private: | 43 | private: |
| 38 | boost::container::flat_map<std::string, std::weak_ptr<Common::FS::IOFile>> cache; | 44 | using ReferenceListType = Common::IntrusiveListBaseTraits<FileReference>::ListType; |
| 45 | std::map<std::string, std::weak_ptr<VfsFile>, std::less<>> cache; | ||
| 46 | ReferenceListType open_references; | ||
| 47 | ReferenceListType closed_references; | ||
| 48 | size_t num_open_files{}; | ||
| 49 | |||
| 50 | private: | ||
| 51 | friend class RealVfsFile; | ||
| 52 | void RefreshReference(const std::string& path, Mode perms, FileReference& reference); | ||
| 53 | void DropReference(std::unique_ptr<FileReference>&& reference); | ||
| 54 | void EvictSingleReference(); | ||
| 55 | |||
| 56 | private: | ||
| 57 | void InsertReferenceIntoList(FileReference& reference); | ||
| 58 | void RemoveReferenceFromList(FileReference& reference); | ||
| 39 | }; | 59 | }; |
| 40 | 60 | ||
| 41 | // An implementation of VfsFile that represents a file on the user's computer. | 61 | // An implementation of VfsFile that represents a file on the user's computer. |
| @@ -57,13 +77,11 @@ public: | |||
| 57 | bool Rename(std::string_view name) override; | 77 | bool Rename(std::string_view name) override; |
| 58 | 78 | ||
| 59 | private: | 79 | private: |
| 60 | RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<Common::FS::IOFile> backing, | 80 | RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference, |
| 61 | const std::string& path, Mode perms = Mode::Read); | 81 | const std::string& path, Mode perms = Mode::Read); |
| 62 | 82 | ||
| 63 | void Close(); | ||
| 64 | |||
| 65 | RealVfsFilesystem& base; | 83 | RealVfsFilesystem& base; |
| 66 | std::shared_ptr<Common::FS::IOFile> backing; | 84 | std::unique_ptr<FileReference> reference; |
| 67 | std::string path; | 85 | std::string path; |
| 68 | std::string parent_path; | 86 | std::string parent_path; |
| 69 | std::vector<std::string> path_components; | 87 | std::vector<std::string> path_components; |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 251a4a880..9bafd8cc0 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -715,7 +715,7 @@ void BufferCache<P>::BindHostIndexBuffer() { | |||
| 715 | 715 | ||
| 716 | template <class P> | 716 | template <class P> |
| 717 | void BufferCache<P>::BindHostVertexBuffers() { | 717 | void BufferCache<P>::BindHostVertexBuffers() { |
| 718 | HostBindings host_bindings; | 718 | HostBindings<typename P::Buffer> host_bindings; |
| 719 | bool any_valid{false}; | 719 | bool any_valid{false}; |
| 720 | auto& flags = maxwell3d->dirty.flags; | 720 | auto& flags = maxwell3d->dirty.flags; |
| 721 | for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) { | 721 | for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) { |
| @@ -741,7 +741,7 @@ void BufferCache<P>::BindHostVertexBuffers() { | |||
| 741 | const u32 stride = maxwell3d->regs.vertex_streams[index].stride; | 741 | const u32 stride = maxwell3d->regs.vertex_streams[index].stride; |
| 742 | const u32 offset = buffer.Offset(binding.cpu_addr); | 742 | const u32 offset = buffer.Offset(binding.cpu_addr); |
| 743 | 743 | ||
| 744 | host_bindings.buffers.push_back(reinterpret_cast<void*>(&buffer)); | 744 | host_bindings.buffers.push_back(&buffer); |
| 745 | host_bindings.offsets.push_back(offset); | 745 | host_bindings.offsets.push_back(offset); |
| 746 | host_bindings.sizes.push_back(binding.size); | 746 | host_bindings.sizes.push_back(binding.size); |
| 747 | host_bindings.strides.push_back(stride); | 747 | host_bindings.strides.push_back(stride); |
| @@ -900,7 +900,7 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() { | |||
| 900 | if (maxwell3d->regs.transform_feedback_enabled == 0) { | 900 | if (maxwell3d->regs.transform_feedback_enabled == 0) { |
| 901 | return; | 901 | return; |
| 902 | } | 902 | } |
| 903 | HostBindings host_bindings; | 903 | HostBindings<typename P::Buffer> host_bindings; |
| 904 | for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) { | 904 | for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) { |
| 905 | const Binding& binding = channel_state->transform_feedback_buffers[index]; | 905 | const Binding& binding = channel_state->transform_feedback_buffers[index]; |
| 906 | if (maxwell3d->regs.transform_feedback.controls[index].varying_count == 0 && | 906 | if (maxwell3d->regs.transform_feedback.controls[index].varying_count == 0 && |
| @@ -913,7 +913,7 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() { | |||
| 913 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | 913 | SynchronizeBuffer(buffer, binding.cpu_addr, size); |
| 914 | 914 | ||
| 915 | const u32 offset = buffer.Offset(binding.cpu_addr); | 915 | const u32 offset = buffer.Offset(binding.cpu_addr); |
| 916 | host_bindings.buffers.push_back(reinterpret_cast<void*>(&buffer)); | 916 | host_bindings.buffers.push_back(&buffer); |
| 917 | host_bindings.offsets.push_back(offset); | 917 | host_bindings.offsets.push_back(offset); |
| 918 | host_bindings.sizes.push_back(binding.size); | 918 | host_bindings.sizes.push_back(binding.size); |
| 919 | } | 919 | } |
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index cf359e241..63a120f7a 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h | |||
| @@ -105,8 +105,9 @@ static constexpr Binding NULL_BINDING{ | |||
| 105 | .buffer_id = NULL_BUFFER_ID, | 105 | .buffer_id = NULL_BUFFER_ID, |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | template <typename Buffer> | ||
| 108 | struct HostBindings { | 109 | struct HostBindings { |
| 109 | boost::container::small_vector<void*, NUM_VERTEX_BUFFERS> buffers; | 110 | boost::container::small_vector<Buffer*, NUM_VERTEX_BUFFERS> buffers; |
| 110 | boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> offsets; | 111 | boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> offsets; |
| 111 | boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> sizes; | 112 | boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> sizes; |
| 112 | boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> strides; | 113 | boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> strides; |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 0cc546a3a..38d553d3c 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -232,12 +232,12 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, | |||
| 232 | } | 232 | } |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) { | 235 | void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) { |
| 236 | for (u32 index = 0; index < bindings.buffers.size(); index++) { | 236 | for (u32 index = 0; index < bindings.buffers.size(); ++index) { |
| 237 | BindVertexBuffer( | 237 | BindVertexBuffer(bindings.min_index + index, *bindings.buffers[index], |
| 238 | bindings.min_index + index, *reinterpret_cast<Buffer*>(bindings.buffers[index]), | 238 | static_cast<u32>(bindings.offsets[index]), |
| 239 | static_cast<u32>(bindings.offsets[index]), static_cast<u32>(bindings.sizes[index]), | 239 | static_cast<u32>(bindings.sizes[index]), |
| 240 | static_cast<u32>(bindings.strides[index])); | 240 | static_cast<u32>(bindings.strides[index])); |
| 241 | } | 241 | } |
| 242 | } | 242 | } |
| 243 | 243 | ||
| @@ -329,10 +329,9 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, Buffer& buffer, | |||
| 329 | static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size)); | 329 | static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size)); |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings) { | 332 | void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings) { |
| 333 | for (u32 index = 0; index < bindings.buffers.size(); index++) { | 333 | for (u32 index = 0; index < bindings.buffers.size(); ++index) { |
| 334 | glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index, | 334 | glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index, bindings.buffers[index]->Handle(), |
| 335 | reinterpret_cast<Buffer*>(bindings.buffers[index])->Handle(), | ||
| 336 | static_cast<GLintptr>(bindings.offsets[index]), | 335 | static_cast<GLintptr>(bindings.offsets[index]), |
| 337 | static_cast<GLsizeiptr>(bindings.sizes[index])); | 336 | static_cast<GLsizeiptr>(bindings.sizes[index])); |
| 338 | } | 337 | } |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index e4e000284..41b746f3b 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -87,7 +87,8 @@ public: | |||
| 87 | void BindIndexBuffer(Buffer& buffer, u32 offset, u32 size); | 87 | void BindIndexBuffer(Buffer& buffer, u32 offset, u32 size); |
| 88 | 88 | ||
| 89 | void BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride); | 89 | void BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride); |
| 90 | void BindVertexBuffers(VideoCommon::HostBindings& bindings); | 90 | |
| 91 | void BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings); | ||
| 91 | 92 | ||
| 92 | void BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size); | 93 | void BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size); |
| 93 | 94 | ||
| @@ -100,7 +101,8 @@ public: | |||
| 100 | bool is_written); | 101 | bool is_written); |
| 101 | 102 | ||
| 102 | void BindTransformFeedbackBuffer(u32 index, Buffer& buffer, u32 offset, u32 size); | 103 | void BindTransformFeedbackBuffer(u32 index, Buffer& buffer, u32 offset, u32 size); |
| 103 | void BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings); | 104 | |
| 105 | void BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings); | ||
| 104 | 106 | ||
| 105 | void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size, | 107 | void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size, |
| 106 | VideoCore::Surface::PixelFormat format); | 108 | VideoCore::Surface::PixelFormat format); |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index d72d99899..8c33722d3 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -501,11 +501,10 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset | |||
| 501 | } | 501 | } |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) { | 504 | void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) { |
| 505 | boost::container::small_vector<VkBuffer, 32> buffer_handles; | 505 | boost::container::small_vector<VkBuffer, 32> buffer_handles; |
| 506 | for (u32 index = 0; index < bindings.buffers.size(); index++) { | 506 | for (u32 index = 0; index < bindings.buffers.size(); ++index) { |
| 507 | auto& buffer = *reinterpret_cast<Buffer*>(bindings.buffers[index]); | 507 | auto handle = bindings.buffers[index]->Handle(); |
| 508 | auto handle = buffer.Handle(); | ||
| 509 | if (handle == VK_NULL_HANDLE) { | 508 | if (handle == VK_NULL_HANDLE) { |
| 510 | bindings.offsets[index] = 0; | 509 | bindings.offsets[index] = 0; |
| 511 | bindings.sizes[index] = VK_WHOLE_SIZE; | 510 | bindings.sizes[index] = VK_WHOLE_SIZE; |
| @@ -521,16 +520,13 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) | |||
| 521 | buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) { | 520 | buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) { |
| 522 | cmdbuf.BindVertexBuffers2EXT( | 521 | cmdbuf.BindVertexBuffers2EXT( |
| 523 | bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(), | 522 | bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(), |
| 524 | reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data()), | 523 | bindings.offsets.data(), bindings.sizes.data(), bindings.strides.data()); |
| 525 | reinterpret_cast<const VkDeviceSize*>(bindings.sizes.data()), | ||
| 526 | reinterpret_cast<const VkDeviceSize*>(bindings.strides.data())); | ||
| 527 | }); | 524 | }); |
| 528 | } else { | 525 | } else { |
| 529 | scheduler.Record([bindings = bindings, | 526 | scheduler.Record([bindings = bindings, |
| 530 | buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) { | 527 | buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) { |
| 531 | cmdbuf.BindVertexBuffers( | 528 | cmdbuf.BindVertexBuffers(bindings.min_index, bindings.max_index - bindings.min_index, |
| 532 | bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(), | 529 | buffer_handles.data(), bindings.offsets.data()); |
| 533 | reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data())); | ||
| 534 | }); | 530 | }); |
| 535 | } | 531 | } |
| 536 | } | 532 | } |
| @@ -556,22 +552,20 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, | |||
| 556 | }); | 552 | }); |
| 557 | } | 553 | } |
| 558 | 554 | ||
| 559 | void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings) { | 555 | void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings) { |
| 560 | if (!device.IsExtTransformFeedbackSupported()) { | 556 | if (!device.IsExtTransformFeedbackSupported()) { |
| 561 | // Already logged in the rasterizer | 557 | // Already logged in the rasterizer |
| 562 | return; | 558 | return; |
| 563 | } | 559 | } |
| 564 | boost::container::small_vector<VkBuffer, 4> buffer_handles; | 560 | boost::container::small_vector<VkBuffer, 4> buffer_handles; |
| 565 | for (u32 index = 0; index < bindings.buffers.size(); index++) { | 561 | for (u32 index = 0; index < bindings.buffers.size(); ++index) { |
| 566 | auto& buffer = *reinterpret_cast<Buffer*>(bindings.buffers[index]); | 562 | buffer_handles.push_back(bindings.buffers[index]->Handle()); |
| 567 | buffer_handles.push_back(buffer.Handle()); | ||
| 568 | } | 563 | } |
| 569 | scheduler.Record( | 564 | scheduler.Record( |
| 570 | [bindings = bindings, buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) { | 565 | [bindings = bindings, buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) { |
| 571 | cmdbuf.BindTransformFeedbackBuffersEXT( | 566 | cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles.size()), |
| 572 | 0, static_cast<u32>(buffer_handles.size()), buffer_handles.data(), | 567 | buffer_handles.data(), bindings.offsets.data(), |
| 573 | reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data()), | 568 | bindings.sizes.data()); |
| 574 | reinterpret_cast<const VkDeviceSize*>(bindings.sizes.data())); | ||
| 575 | }); | 569 | }); |
| 576 | } | 570 | } |
| 577 | 571 | ||
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 92d3e9f32..cdeef8846 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -97,10 +97,12 @@ public: | |||
| 97 | void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count); | 97 | void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count); |
| 98 | 98 | ||
| 99 | void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride); | 99 | void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride); |
| 100 | void BindVertexBuffers(VideoCommon::HostBindings& bindings); | 100 | |
| 101 | void BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings); | ||
| 101 | 102 | ||
| 102 | void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size); | 103 | void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size); |
| 103 | void BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings); | 104 | |
| 105 | void BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings); | ||
| 104 | 106 | ||
| 105 | std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage, | 107 | std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage, |
| 106 | [[maybe_unused]] u32 binding_index, u32 size) { | 108 | [[maybe_unused]] u32 binding_index, u32 size) { |