diff options
Diffstat (limited to 'src/common')
28 files changed, 267 insertions, 122 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index d9424ea91..6a3f1fe08 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,13 +1,16 @@ # Generate cpp with Git revision from template -# Also if this is a CI build, add the build name (ie: Nightly, Bleeding Edge) to the scm_rev file as well +# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well set(REPO_NAME "") +set(BUILD_VERSION "0") if ($ENV{CI}) if ($ENV{TRAVIS}) set(BUILD_REPOSITORY $ENV{TRAVIS_REPO_SLUG}) + set(BUILD_TAG $ENV{TRAVIS_TAG}) elseif($ENV{APPVEYOR}) set(BUILD_REPOSITORY $ENV{APPVEYOR_REPO_NAME}) + set(BUILD_TAG $ENV{APPVEYOR_REPO_TAG_NAME}) endif() - # regex capture the string nightly or bleeding-edge into CMAKE_MATCH_1 + # regex capture the string nightly or canary into CMAKE_MATCH_1 string(REGEX MATCH "yuzu-emu/yuzu-?(.*)" OUTVAR ${BUILD_REPOSITORY}) if (${CMAKE_MATCH_COUNT} GREATER 0) # capitalize the first letter of each word in the repo name. @@ -16,10 +19,21 @@ if ($ENV{CI}) string(SUBSTRING ${WORD} 0 1 FIRST_LETTER) string(SUBSTRING ${WORD} 1 -1 REMAINDER) string(TOUPPER ${FIRST_LETTER} FIRST_LETTER) - # this leaves a trailing space on the last word, but we actually want that - # because of how it's styled in the title bar. - set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER} ") + set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}") endforeach() + if (BUILD_TAG) + string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG}) + if (${CMAKE_MATCH_COUNT} GREATER 0) + set(BUILD_VERSION ${CMAKE_MATCH_1}) + endif() + if (BUILD_VERSION) + # This leaves a trailing space on the last word, but we actually want that + # because of how it's styled in the title bar. + set(BUILD_FULLNAME "${REPO_NAME} #${BUILD_VERSION} ") + else() + set(BUILD_FULLNAME "") + endif() + endif() endif() endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp" @ONLY) @@ -57,6 +71,7 @@ add_library(common STATIC param_package.cpp param_package.h quaternion.h + ring_buffer.h scm_rev.cpp scm_rev.h scope_exit.h diff --git a/src/common/alignment.h b/src/common/alignment.h index b9dd38746..225770fab 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h @@ -8,13 +8,13 @@ namespace Common { template <typename T> -constexpr T AlignUp(T value, size_t size) { +constexpr T AlignUp(T value, std::size_t size) { static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); return static_cast<T>(value + (size - value % size) % size); } template <typename T> -constexpr T AlignDown(T value, size_t size) { +constexpr T AlignDown(T value, std::size_t size) { static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); return static_cast<T>(value - value % size); } diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 732201de7..bf803da8d 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -129,8 +129,8 @@ private: public: /// Constants to allow limited introspection of fields if needed - static constexpr size_t position = Position; - static constexpr size_t bits = Bits; + static constexpr std::size_t position = Position; + static constexpr std::size_t bits = Bits; static constexpr StorageType mask = (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position; /** diff --git a/src/common/bit_set.h b/src/common/bit_set.h index 5a197d8c1..5cd1352b2 100644 --- a/src/common/bit_set.h +++ b/src/common/bit_set.h @@ -170,14 +170,14 @@ public: m_val |= (IntTy)1 << bit; } - static BitSet AllTrue(size_t count) { + static BitSet AllTrue(std::size_t count) { return BitSet(count == sizeof(IntTy) * 8 ? ~(IntTy)0 : (((IntTy)1 << count) - 1)); } - Ref operator[](size_t bit) { + Ref operator[](std::size_t bit) { return Ref(this, (IntTy)1 << bit); } - const Ref operator[](size_t bit) const { + const Ref operator[](std::size_t bit) const { return (*const_cast<BitSet*>(this))[bit]; } bool operator==(BitSet other) const { diff --git a/src/common/cityhash.cpp b/src/common/cityhash.cpp index de31ffbd8..4e1d874b5 100644 --- a/src/common/cityhash.cpp +++ b/src/common/cityhash.cpp @@ -114,7 +114,7 @@ static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) { return b; } -static uint64 HashLen0to16(const char* s, size_t len) { +static uint64 HashLen0to16(const char* s, std::size_t len) { if (len >= 8) { uint64 mul = k2 + len * 2; uint64 a = Fetch64(s) + k2; @@ -141,7 +141,7 @@ static uint64 HashLen0to16(const char* s, size_t len) { // This probably works well for 16-byte strings as well, but it may be overkill // in that case. -static uint64 HashLen17to32(const char* s, size_t len) { +static uint64 HashLen17to32(const char* s, std::size_t len) { uint64 mul = k2 + len * 2; uint64 a = Fetch64(s) * k1; uint64 b = Fetch64(s + 8); @@ -170,7 +170,7 @@ static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint } // Return an 8-byte hash for 33 to 64 bytes. -static uint64 HashLen33to64(const char* s, size_t len) { +static uint64 HashLen33to64(const char* s, std::size_t len) { uint64 mul = k2 + len * 2; uint64 a = Fetch64(s) * k2; uint64 b = Fetch64(s + 8); @@ -191,7 +191,7 @@ static uint64 HashLen33to64(const char* s, size_t len) { return b + x; } -uint64 CityHash64(const char* s, size_t len) { +uint64 CityHash64(const char* s, std::size_t len) { if (len <= 32) { if (len <= 16) { return HashLen0to16(s, len); @@ -212,7 +212,7 @@ uint64 CityHash64(const char* s, size_t len) { x = x * k1 + Fetch64(s); // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. - len = (len - 1) & ~static_cast<size_t>(63); + len = (len - 1) & ~static_cast<std::size_t>(63); do { x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; @@ -229,17 +229,17 @@ uint64 CityHash64(const char* s, size_t len) { HashLen16(v.second, w.second) + x); } -uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) { +uint64 CityHash64WithSeed(const char* s, std::size_t len, uint64 seed) { return CityHash64WithSeeds(s, len, k2, seed); } -uint64 CityHash64WithSeeds(const char* s, size_t len, uint64 seed0, uint64 seed1) { +uint64 CityHash64WithSeeds(const char* s, std::size_t len, uint64 seed0, uint64 seed1) { return HashLen16(CityHash64(s, len) - seed0, seed1); } // A subroutine for CityHash128(). Returns a decent 128-bit hash for strings // of any length representable in signed long. Based on City and Murmur. -static uint128 CityMurmur(const char* s, size_t len, uint128 seed) { +static uint128 CityMurmur(const char* s, std::size_t len, uint128 seed) { uint64 a = Uint128Low64(seed); uint64 b = Uint128High64(seed); uint64 c = 0; @@ -269,7 +269,7 @@ static uint128 CityMurmur(const char* s, size_t len, uint128 seed) { return uint128(a ^ b, HashLen16(b, a)); } -uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) { +uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed) { if (len < 128) { return CityMurmur(s, len, seed); } @@ -313,7 +313,7 @@ uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) { w.first *= 9; v.first *= k0; // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. - for (size_t tail_done = 0; tail_done < len;) { + for (std::size_t tail_done = 0; tail_done < len;) { tail_done += 32; y = Rotate(x + y, 42) * k0 + v.second; w.first += Fetch64(s + len - tail_done + 16); @@ -331,7 +331,7 @@ uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) { return uint128(HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second)); } -uint128 CityHash128(const char* s, size_t len) { +uint128 CityHash128(const char* s, std::size_t len) { return len >= 16 ? CityHash128WithSeed(s + 16, len - 16, uint128(Fetch64(s), Fetch64(s + 8) + k0)) : CityHash128WithSeed(s, len, uint128(k0, k1)); diff --git a/src/common/cityhash.h b/src/common/cityhash.h index bcebdb150..4b94f8e18 100644 --- a/src/common/cityhash.h +++ b/src/common/cityhash.h @@ -63,7 +63,7 @@ #include <utility> #include <stdint.h> -#include <stdlib.h> // for size_t. +#include <stdlib.h> // for std::size_t. namespace Common { @@ -77,22 +77,22 @@ inline uint64_t Uint128High64(const uint128& x) { } // Hash function for a byte array. -uint64_t CityHash64(const char* buf, size_t len); +uint64_t CityHash64(const char* buf, std::size_t len); // Hash function for a byte array. For convenience, a 64-bit seed is also // hashed into the result. -uint64_t CityHash64WithSeed(const char* buf, size_t len, uint64_t seed); +uint64_t CityHash64WithSeed(const char* buf, std::size_t len, uint64_t seed); // Hash function for a byte array. For convenience, two seeds are also // hashed into the result. -uint64_t CityHash64WithSeeds(const char* buf, size_t len, uint64_t seed0, uint64_t seed1); +uint64_t CityHash64WithSeeds(const char* buf, std::size_t len, uint64_t seed0, uint64_t seed1); // Hash function for a byte array. -uint128 CityHash128(const char* s, size_t len); +uint128 CityHash128(const char* s, std::size_t len); // Hash function for a byte array. For convenience, a 128-bit seed is also // hashed into the result. -uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed); +uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed); // Hash 128 input bits down to 64 bits of output. // This is intended to be a reasonably good hash function. diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index baa721481..21a0b9738 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -76,7 +76,7 @@ namespace FileUtil { // Modifies argument. static void StripTailDirSlashes(std::string& fname) { if (fname.length() > 1) { - size_t i = fname.length(); + std::size_t i = fname.length(); while (i > 0 && fname[i - 1] == DIR_SEP_CHR) --i; fname.resize(i); @@ -201,7 +201,7 @@ bool CreateFullPath(const std::string& fullPath) { return true; } - size_t position = 0; + std::size_t position = 0; while (true) { // Find next sub path position = fullPath.find(DIR_SEP_CHR, position); @@ -299,7 +299,7 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { std::array<char, 1024> buffer; while (!feof(input.get())) { // read input - size_t rnum = fread(buffer.data(), sizeof(char), buffer.size(), input.get()); + std::size_t rnum = fread(buffer.data(), sizeof(char), buffer.size(), input.get()); if (rnum != buffer.size()) { if (ferror(input.get()) != 0) { LOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}", @@ -309,7 +309,7 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { } // write output - size_t wnum = fwrite(buffer.data(), sizeof(char), rnum, output.get()); + std::size_t wnum = fwrite(buffer.data(), sizeof(char), rnum, output.get()); if (wnum != rnum) { LOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename, destFilename, GetLastErrorMsg()); @@ -756,11 +756,11 @@ std::string GetNANDRegistrationDir(bool system) { return GetUserPath(UserPath::NANDDir) + "user/Contents/registered/"; } -size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename) { +std::size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename) { return FileUtil::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); } -size_t ReadFileToString(bool text_file, const char* filename, std::string& str) { +std::size_t ReadFileToString(bool text_file, const char* filename, std::string& str) { IOFile file(filename, text_file ? "r" : "rb"); if (!file.IsOpen()) @@ -829,7 +829,7 @@ std::vector<std::string> SplitPathComponents(std::string_view filename) { std::string_view GetParentPath(std::string_view path) { const auto name_bck_index = path.rfind('\\'); const auto name_fwd_index = path.rfind('/'); - size_t name_index; + std::size_t name_index; if (name_bck_index == std::string_view::npos || name_fwd_index == std::string_view::npos) { name_index = std::min(name_bck_index, name_fwd_index); @@ -868,7 +868,7 @@ std::string_view GetFilename(std::string_view path) { } std::string_view GetExtensionFromFilename(std::string_view name) { - const size_t index = name.rfind('.'); + const std::size_t index = name.rfind('.'); if (index == std::string_view::npos) { return {}; diff --git a/src/common/file_util.h b/src/common/file_util.h index 2f13d0b6b..24c1e413c 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -143,8 +143,9 @@ const std::string& GetExeDirectory(); std::string AppDataRoamingDirectory(); #endif -size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename); -size_t ReadFileToString(bool text_file, const char* filename, std::string& str); +std::size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename); + +std::size_t ReadFileToString(bool text_file, const char* filename, std::string& str); /** * Splits the filename into 8.3 format @@ -177,10 +178,10 @@ std::string_view RemoveTrailingSlash(std::string_view path); // Creates a new vector containing indices [first, last) from the original. template <typename T> -std::vector<T> SliceVector(const std::vector<T>& vector, size_t first, size_t last) { +std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first, std::size_t last) { if (first >= last) return {}; - last = std::min<size_t>(last, vector.size()); + last = std::min<std::size_t>(last, vector.size()); return std::vector<T>(vector.begin() + first, vector.begin() + first + last); } @@ -213,47 +214,47 @@ public: bool Close(); template <typename T> - size_t ReadArray(T* data, size_t length) const { + std::size_t ReadArray(T* data, std::size_t length) const { static_assert(std::is_trivially_copyable_v<T>, "Given array does not consist of trivially copyable objects"); if (!IsOpen()) { - return std::numeric_limits<size_t>::max(); + return std::numeric_limits<std::size_t>::max(); } return std::fread(data, sizeof(T), length, m_file); } template <typename T> - size_t WriteArray(const T* data, size_t length) { + std::size_t WriteArray(const T* data, std::size_t length) { static_assert(std::is_trivially_copyable_v<T>, "Given array does not consist of trivially copyable objects"); if (!IsOpen()) { - return std::numeric_limits<size_t>::max(); + return std::numeric_limits<std::size_t>::max(); } return std::fwrite(data, sizeof(T), length, m_file); } template <typename T> - size_t ReadBytes(T* data, size_t length) const { + std::size_t ReadBytes(T* data, std::size_t length) const { static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); return ReadArray(reinterpret_cast<char*>(data), length); } template <typename T> - size_t WriteBytes(const T* data, size_t length) { + std::size_t WriteBytes(const T* data, std::size_t length) { static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); return WriteArray(reinterpret_cast<const char*>(data), length); } template <typename T> - size_t WriteObject(const T& object) { + std::size_t WriteObject(const T& object) { static_assert(!std::is_pointer_v<T>, "WriteObject arguments must not be a pointer"); return WriteArray(&object, 1); } - size_t WriteString(const std::string& str) { + std::size_t WriteString(const std::string& str) { return WriteArray(str.c_str(), str.length()); } diff --git a/src/common/hash.h b/src/common/hash.h index 2c761e545..40194d1ee 100644 --- a/src/common/hash.h +++ b/src/common/hash.h @@ -17,7 +17,7 @@ namespace Common { * @param len Length of data (in bytes) to compute hash over * @returns 64-bit hash value that was computed over the data block */ -static inline u64 ComputeHash64(const void* data, size_t len) { +static inline u64 ComputeHash64(const void* data, std::size_t len) { return CityHash64(static_cast<const char*>(data), len); } @@ -63,7 +63,7 @@ struct HashableStruct { return !(*this == o); }; - size_t Hash() const { + std::size_t Hash() const { return Common::ComputeStructHash64(state); } }; diff --git a/src/common/hex_util.cpp b/src/common/hex_util.cpp index 8e0a9e46f..589ae5cbf 100644 --- a/src/common/hex_util.cpp +++ b/src/common/hex_util.cpp @@ -18,7 +18,7 @@ u8 ToHexNibble(char c1) { return 0; } -std::array<u8, 16> operator""_array16(const char* str, size_t len) { +std::array<u8, 16> operator""_array16(const char* str, std::size_t len) { if (len != 32) { LOG_ERROR(Common, "Attempting to parse string to array that is not of correct size (expected=32, " @@ -29,7 +29,7 @@ std::array<u8, 16> operator""_array16(const char* str, size_t len) { return HexStringToArray<16>(str); } -std::array<u8, 32> operator""_array32(const char* str, size_t len) { +std::array<u8, 32> operator""_array32(const char* str, std::size_t len) { if (len != 64) { LOG_ERROR(Common, "Attempting to parse string to array that is not of correct size (expected=64, " diff --git a/src/common/hex_util.h b/src/common/hex_util.h index 5fb79bb72..863a5ccd9 100644 --- a/src/common/hex_util.h +++ b/src/common/hex_util.h @@ -14,20 +14,20 @@ namespace Common { u8 ToHexNibble(char c1); -template <size_t Size, bool le = false> +template <std::size_t Size, bool le = false> std::array<u8, Size> HexStringToArray(std::string_view str) { std::array<u8, Size> out{}; if constexpr (le) { - for (size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) + for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); } else { - for (size_t i = 0; i < 2 * Size; i += 2) + for (std::size_t i = 0; i < 2 * Size; i += 2) out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); } return out; } -template <size_t Size> +template <std::size_t Size> std::string HexArrayToString(std::array<u8, Size> array, bool upper = true) { std::string out; for (u8 c : array) @@ -35,7 +35,7 @@ std::string HexArrayToString(std::array<u8, Size> array, bool upper = true) { return out; } -std::array<u8, 0x10> operator"" _array16(const char* str, size_t len); -std::array<u8, 0x20> operator"" _array32(const char* str, size_t len); +std::array<u8, 0x10> operator"" _array16(const char* str, std::size_t len); +std::array<u8, 0x20> operator"" _array32(const char* str, std::size_t len); } // namespace Common diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 1323f8d0f..efd776db6 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -135,7 +135,7 @@ FileBackend::FileBackend(const std::string& filename) void FileBackend::Write(const Entry& entry) { // prevent logs from going over the maximum size (in case its spamming and the user doesn't // know) - constexpr size_t MAX_BYTES_WRITTEN = 50 * 1024L * 1024L; + constexpr std::size_t MAX_BYTES_WRITTEN = 50 * 1024L * 1024L; if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) { return; } diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index b3f4b9cef..11edbf1b6 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -100,7 +100,7 @@ public: private: FileUtil::IOFile file; - size_t bytes_written; + std::size_t bytes_written; }; void AddBackend(std::unique_ptr<Backend> backend); diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 2dd331152..2eccbcd8d 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -71,7 +71,7 @@ void Filter::ResetAll(Level level) { } void Filter::SetClassLevel(Class log_class, Level level) { - class_levels[static_cast<size_t>(log_class)] = level; + class_levels[static_cast<std::size_t>(log_class)] = level; } void Filter::ParseFilterString(std::string_view filter_view) { @@ -93,7 +93,8 @@ void Filter::ParseFilterString(std::string_view filter_view) { } bool Filter::CheckMessage(Class log_class, Level level) const { - return static_cast<u8>(level) >= static_cast<u8>(class_levels[static_cast<size_t>(log_class)]); + return static_cast<u8>(level) >= + static_cast<u8>(class_levels[static_cast<std::size_t>(log_class)]); } bool Filter::IsDebug() const { diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h index d5ffc5a58..773df6f2c 100644 --- a/src/common/logging/filter.h +++ b/src/common/logging/filter.h @@ -19,7 +19,7 @@ namespace Log { class Filter { public: /// Initializes the filter with all classes having `default_level` as the minimum level. - Filter(Level default_level = Level::Info); + explicit Filter(Level default_level = Level::Info); /// Resets the filter so that all classes have `level` as the minimum displayed level. void ResetAll(Level level); @@ -49,6 +49,6 @@ public: bool IsDebug() const; private: - std::array<Level, (size_t)Class::Count> class_levels; + std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; }; } // namespace Log diff --git a/src/common/logging/log.h b/src/common/logging/log.h index e12f47f8f..4d577524f 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -12,14 +12,14 @@ namespace Log { /// Specifies the severity or level of detail of the log message. enum class Level : u8 { Trace, ///< Extremely detailed and repetitive debugging information that is likely to - /// pollute logs. + ///< pollute logs. Debug, ///< Less detailed debugging information. Info, ///< Status information from important points during execution. Warning, ///< Minor or potential problems found during execution of a task. Error, ///< Major problems found during execution of a task that prevent it from being - /// completed. - Critical, ///< Major problems during execution that threathen the stability of the entire - /// application. + ///< completed. + Critical, ///< Major problems during execution that threaten the stability of the entire + ///< application. Count ///< Total number of logging levels }; @@ -49,7 +49,7 @@ enum class Class : ClassType { Kernel, ///< The HLE implementation of the CTR kernel Kernel_SVC, ///< Kernel system calls Service, ///< HLE implementation of system services. Each major service - /// should have its own subclass. + ///< should have its own subclass. Service_ACC, ///< The ACC (Accounts) service Service_AM, ///< The AM (Applet manager) service Service_AOC, ///< The AOC (AddOn Content) service diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h index 9609cec7c..b6d9e57c8 100644 --- a/src/common/logging/text_formatter.h +++ b/src/common/logging/text_formatter.h @@ -15,6 +15,6 @@ struct Entry; std::string FormatLogMessage(const Entry& entry); /// Formats and prints a log entry to stderr. void PrintMessage(const Entry& entry); -/// Prints the same message as `PrintMessage`, but colored acoording to the severity level. +/// Prints the same message as `PrintMessage`, but colored according to the severity level. void PrintColoredMessage(const Entry& entry); } // namespace Log diff --git a/src/common/memory_util.cpp b/src/common/memory_util.cpp index 09462ccee..9736fb12a 100644 --- a/src/common/memory_util.cpp +++ b/src/common/memory_util.cpp @@ -25,7 +25,7 @@ // This is purposely not a full wrapper for virtualalloc/mmap, but it // provides exactly the primitive operations that Dolphin needs. -void* AllocateExecutableMemory(size_t size, bool low) { +void* AllocateExecutableMemory(std::size_t size, bool low) { #if defined(_WIN32) void* ptr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else @@ -74,7 +74,7 @@ void* AllocateExecutableMemory(size_t size, bool low) { return ptr; } -void* AllocateMemoryPages(size_t size) { +void* AllocateMemoryPages(std::size_t size) { #ifdef _WIN32 void* ptr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE); #else @@ -90,7 +90,7 @@ void* AllocateMemoryPages(size_t size) { return ptr; } -void* AllocateAlignedMemory(size_t size, size_t alignment) { +void* AllocateAlignedMemory(std::size_t size, std::size_t alignment) { #ifdef _WIN32 void* ptr = _aligned_malloc(size, alignment); #else @@ -109,7 +109,7 @@ void* AllocateAlignedMemory(size_t size, size_t alignment) { return ptr; } -void FreeMemoryPages(void* ptr, size_t size) { +void FreeMemoryPages(void* ptr, std::size_t size) { if (ptr) { #ifdef _WIN32 if (!VirtualFree(ptr, 0, MEM_RELEASE)) @@ -130,7 +130,7 @@ void FreeAlignedMemory(void* ptr) { } } -void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) { +void WriteProtectMemory(void* ptr, std::size_t size, bool allowExecute) { #ifdef _WIN32 DWORD oldValue; if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue)) @@ -140,7 +140,7 @@ void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) { #endif } -void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) { +void UnWriteProtectMemory(void* ptr, std::size_t size, bool allowExecute) { #ifdef _WIN32 DWORD oldValue; if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, diff --git a/src/common/memory_util.h b/src/common/memory_util.h index 76ca5a30c..aad071979 100644 --- a/src/common/memory_util.h +++ b/src/common/memory_util.h @@ -7,13 +7,13 @@ #include <cstddef> #include <string> -void* AllocateExecutableMemory(size_t size, bool low = true); -void* AllocateMemoryPages(size_t size); -void FreeMemoryPages(void* ptr, size_t size); -void* AllocateAlignedMemory(size_t size, size_t alignment); +void* AllocateExecutableMemory(std::size_t size, bool low = true); +void* AllocateMemoryPages(std::size_t size); +void FreeMemoryPages(void* ptr, std::size_t size); +void* AllocateAlignedMemory(std::size_t size, std::size_t alignment); void FreeAlignedMemory(void* ptr); -void WriteProtectMemory(void* ptr, size_t size, bool executable = false); -void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute = false); +void WriteProtectMemory(void* ptr, std::size_t size, bool executable = false); +void UnWriteProtectMemory(void* ptr, std::size_t size, bool allowExecute = false); std::string MemUsage(); inline int GetPageSize() { diff --git a/src/common/misc.cpp b/src/common/misc.cpp index 3fa8a3bc4..68cb86cd1 100644 --- a/src/common/misc.cpp +++ b/src/common/misc.cpp @@ -16,7 +16,7 @@ // Call directly after the command or use the error num. // This function might change the error code. std::string GetLastErrorMsg() { - static const size_t buff_size = 255; + static const std::size_t buff_size = 255; char err_str[buff_size]; #ifdef _WIN32 diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h new file mode 100644 index 000000000..abe3b4dc2 --- /dev/null +++ b/src/common/ring_buffer.h @@ -0,0 +1,119 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <algorithm> +#include <array> +#include <atomic> +#include <cstddef> +#include <cstring> +#include <new> +#include <type_traits> +#include <vector> +#include "common/common_types.h" + +namespace Common { + +/// SPSC ring buffer +/// @tparam T Element type +/// @tparam capacity Number of slots in ring buffer +/// @tparam granularity Slot size in terms of number of elements +template <typename T, std::size_t capacity, std::size_t granularity = 1> +class RingBuffer { + /// A "slot" is made of `granularity` elements of `T`. + static constexpr std::size_t slot_size = granularity * sizeof(T); + // T must be safely memcpy-able and have a trivial default constructor. + static_assert(std::is_trivial_v<T>); + // Ensure capacity is sensible. + static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2 / granularity); + static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two"); + // Ensure lock-free. + static_assert(std::atomic_size_t::is_always_lock_free); + +public: + /// Pushes slots into the ring buffer + /// @param new_slots Pointer to the slots to push + /// @param slot_count Number of slots to push + /// @returns The number of slots actually pushed + std::size_t Push(const void* new_slots, std::size_t slot_count) { + const std::size_t write_index = m_write_index.load(); + const std::size_t slots_free = capacity + m_read_index.load() - write_index; + const std::size_t push_count = std::min(slot_count, slots_free); + + const std::size_t pos = write_index % capacity; + const std::size_t first_copy = std::min(capacity - pos, push_count); + const std::size_t second_copy = push_count - first_copy; + + const char* in = static_cast<const char*>(new_slots); + std::memcpy(m_data.data() + pos * granularity, in, first_copy * slot_size); + in += first_copy * slot_size; + std::memcpy(m_data.data(), in, second_copy * slot_size); + + m_write_index.store(write_index + push_count); + + return push_count; + } + + std::size_t Push(const std::vector<T>& input) { + return Push(input.data(), input.size()); + } + + /// Pops slots from the ring buffer + /// @param output Where to store the popped slots + /// @param max_slots Maximum number of slots to pop + /// @returns The number of slots actually popped + std::size_t Pop(void* output, std::size_t max_slots = ~std::size_t(0)) { + const std::size_t read_index = m_read_index.load(); + const std::size_t slots_filled = m_write_index.load() - read_index; + const std::size_t pop_count = std::min(slots_filled, max_slots); + + const std::size_t pos = read_index % capacity; + const std::size_t first_copy = std::min(capacity - pos, pop_count); + const std::size_t second_copy = pop_count - first_copy; + + char* out = static_cast<char*>(output); + std::memcpy(out, m_data.data() + pos * granularity, first_copy * slot_size); + out += first_copy * slot_size; + std::memcpy(out, m_data.data(), second_copy * slot_size); + + m_read_index.store(read_index + pop_count); + + return pop_count; + } + + std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) { + std::vector<T> out(std::min(max_slots, capacity) * granularity); + const std::size_t count = Pop(out.data(), out.size() / granularity); + out.resize(count * granularity); + return out; + } + + /// @returns Number of slots used + std::size_t Size() const { + return m_write_index.load() - m_read_index.load(); + } + + /// @returns Maximum size of ring buffer + constexpr std::size_t Capacity() const { + return capacity; + } + +private: + // It is important to align the below variables for performance reasons: + // Having them on the same cache-line would result in false-sharing between them. + // TODO: Remove this ifdef whenever clang and GCC support + // std::hardware_destructive_interference_size. +#if defined(_MSC_VER) && _MSC_VER >= 1911 + alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_read_index{0}; + alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_write_index{0}; +#else + alignas(128) std::atomic_size_t m_read_index{0}; + alignas(128) std::atomic_size_t m_write_index{0}; +#endif + + std::array<T, granularity * capacity> m_data; +}; + +} // namespace Common diff --git a/src/common/scm_rev.cpp.in b/src/common/scm_rev.cpp.in index 4083095d5..2b1727769 100644 --- a/src/common/scm_rev.cpp.in +++ b/src/common/scm_rev.cpp.in @@ -9,6 +9,8 @@ #define GIT_DESC "@GIT_DESC@" #define BUILD_NAME "@REPO_NAME@" #define BUILD_DATE "@BUILD_DATE@" +#define BUILD_FULLNAME "@BUILD_FULLNAME@" +#define BUILD_VERSION "@BUILD_VERSION@" namespace Common { @@ -17,6 +19,8 @@ const char g_scm_branch[] = GIT_BRANCH; const char g_scm_desc[] = GIT_DESC; const char g_build_name[] = BUILD_NAME; const char g_build_date[] = BUILD_DATE; +const char g_build_fullname[] = BUILD_FULLNAME; +const char g_build_version[] = BUILD_VERSION; } // namespace diff --git a/src/common/scm_rev.h b/src/common/scm_rev.h index db0f4a947..af9a9daed 100644 --- a/src/common/scm_rev.h +++ b/src/common/scm_rev.h @@ -11,5 +11,7 @@ extern const char g_scm_branch[]; extern const char g_scm_desc[]; extern const char g_build_name[]; extern const char g_build_date[]; +extern const char g_build_fullname[]; +extern const char g_build_version[]; } // namespace Common diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 0ca663032..c9a5425a7 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -37,7 +37,7 @@ std::string ToUpper(std::string str) { } // For Debugging. Read out an u8 array. -std::string ArrayToString(const u8* data, size_t size, int line_len, bool spaces) { +std::string ArrayToString(const u8* data, std::size_t size, int line_len, bool spaces) { std::ostringstream oss; oss << std::setfill('0') << std::hex; @@ -60,7 +60,7 @@ std::string StringFromBuffer(const std::vector<u8>& data) { // Turns " hej " into "hej". Also handles tabs. std::string StripSpaces(const std::string& str) { - const size_t s = str.find_first_not_of(" \t\r\n"); + const std::size_t s = str.find_first_not_of(" \t\r\n"); if (str.npos != s) return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1); @@ -121,10 +121,10 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _ if (full_path.empty()) return false; - size_t dir_end = full_path.find_last_of("/" + std::size_t dir_end = full_path.find_last_of("/" // windows needs the : included for something like just "C:" to be considered a directory #ifdef _WIN32 - "\\:" + "\\:" #endif ); if (std::string::npos == dir_end) @@ -132,7 +132,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _ else dir_end += 1; - size_t fname_end = full_path.rfind('.'); + std::size_t fname_end = full_path.rfind('.'); if (fname_end < dir_end || std::string::npos == fname_end) fname_end = full_path.size(); @@ -172,7 +172,7 @@ void SplitString(const std::string& str, const char delim, std::vector<std::stri } std::string TabsToSpaces(int tab_size, std::string in) { - size_t i = 0; + std::size_t i = 0; while ((i = in.find('\t')) != std::string::npos) { in.replace(i, 1, tab_size, ' '); @@ -182,7 +182,7 @@ std::string TabsToSpaces(int tab_size, std::string in) { } std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest) { - size_t pos = 0; + std::size_t pos = 0; if (src == dest) return result; @@ -280,22 +280,22 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& return {}; } - const size_t in_bytes = sizeof(T) * input.size(); + const std::size_t in_bytes = sizeof(T) * input.size(); // Multiply by 4, which is the max number of bytes to encode a codepoint - const size_t out_buffer_size = 4 * in_bytes; + const std::size_t out_buffer_size = 4 * in_bytes; std::string out_buffer(out_buffer_size, '\0'); auto src_buffer = &input[0]; - size_t src_bytes = in_bytes; + std::size_t src_bytes = in_bytes; auto dst_buffer = &out_buffer[0]; - size_t dst_bytes = out_buffer.size(); + std::size_t dst_bytes = out_buffer.size(); while (0 != src_bytes) { - size_t const iconv_result = + std::size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes, &dst_buffer, &dst_bytes); - if (static_cast<size_t>(-1) == iconv_result) { + if (static_cast<std::size_t>(-1) == iconv_result) { if (EILSEQ == errno || EINVAL == errno) { // Try to skip the bad character if (0 != src_bytes) { @@ -326,22 +326,22 @@ std::u16string UTF8ToUTF16(const std::string& input) { return {}; } - const size_t in_bytes = sizeof(char) * input.size(); + const std::size_t in_bytes = sizeof(char) * input.size(); // Multiply by 4, which is the max number of bytes to encode a codepoint - const size_t out_buffer_size = 4 * sizeof(char16_t) * in_bytes; + const std::size_t out_buffer_size = 4 * sizeof(char16_t) * in_bytes; std::u16string out_buffer(out_buffer_size, char16_t{}); char* src_buffer = const_cast<char*>(&input[0]); - size_t src_bytes = in_bytes; + std::size_t src_bytes = in_bytes; char* dst_buffer = (char*)(&out_buffer[0]); - size_t dst_bytes = out_buffer.size(); + std::size_t dst_bytes = out_buffer.size(); while (0 != src_bytes) { - size_t const iconv_result = + std::size_t const iconv_result = iconv(conv_desc, &src_buffer, &src_bytes, &dst_buffer, &dst_bytes); - if (static_cast<size_t>(-1) == iconv_result) { + if (static_cast<std::size_t>(-1) == iconv_result) { if (EILSEQ == errno || EINVAL == errno) { // Try to skip the bad character if (0 != src_bytes) { @@ -381,8 +381,8 @@ std::string SHIFTJISToUTF8(const std::string& input) { #endif -std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, size_t max_len) { - size_t len = 0; +std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len) { + std::size_t len = 0; while (len < max_len && buffer[len] != '\0') ++len; diff --git a/src/common/string_util.h b/src/common/string_util.h index 4a2143b59..dcca6bc38 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -19,7 +19,7 @@ std::string ToLower(std::string str); /// Make a string uppercase std::string ToUpper(std::string str); -std::string ArrayToString(const u8* data, size_t size, int line_len = 20, bool spaces = true); +std::string ArrayToString(const u8* data, std::size_t size, int line_len = 20, bool spaces = true); std::string StringFromBuffer(const std::vector<u8>& data); @@ -118,7 +118,7 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) { * Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't * NUL-terminated then the string ends at max_len characters. */ -std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, size_t max_len); +std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len); /** * Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's diff --git a/src/common/thread.h b/src/common/thread.h index 9465e1de7..12a1c095c 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -60,12 +60,12 @@ private: class Barrier { public: - explicit Barrier(size_t count_) : count(count_), waiting(0), generation(0) {} + explicit Barrier(std::size_t count_) : count(count_), waiting(0), generation(0) {} /// Blocks until all "count" threads have called Sync() void Sync() { std::unique_lock<std::mutex> lk(mutex); - const size_t current_generation = generation; + const std::size_t current_generation = generation; if (++waiting == count) { generation++; @@ -80,9 +80,9 @@ public: private: std::condition_variable condvar; std::mutex mutex; - const size_t count; - size_t waiting; - size_t generation; // Incremented once each time the barrier is used + const std::size_t count; + std::size_t waiting; + std::size_t generation; // Incremented once each time the barrier is used }; void SleepCurrentThread(int ms); diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h index 927da9187..636a5c0f9 100644 --- a/src/common/x64/xbyak_abi.h +++ b/src/common/x64/xbyak_abi.h @@ -97,7 +97,7 @@ const BitSet32 ABI_ALL_CALLEE_SAVED = BuildRegSet({ Xbyak::util::xmm15, }); -constexpr size_t ABI_SHADOW_SPACE = 0x20; +constexpr std::size_t ABI_SHADOW_SPACE = 0x20; #else @@ -147,22 +147,23 @@ const BitSet32 ABI_ALL_CALLEE_SAVED = BuildRegSet({ Xbyak::util::r15, }); -constexpr size_t ABI_SHADOW_SPACE = 0; +constexpr std::size_t ABI_SHADOW_SPACE = 0; #endif -inline void ABI_CalculateFrameSize(BitSet32 regs, size_t rsp_alignment, size_t needed_frame_size, - s32* out_subtraction, s32* out_xmm_offset) { +inline void ABI_CalculateFrameSize(BitSet32 regs, std::size_t rsp_alignment, + std::size_t needed_frame_size, s32* out_subtraction, + s32* out_xmm_offset) { int count = (regs & ABI_ALL_GPRS).Count(); rsp_alignment -= count * 8; - size_t subtraction = 0; + std::size_t subtraction = 0; int xmm_count = (regs & ABI_ALL_XMMS).Count(); if (xmm_count) { // If we have any XMMs to save, we must align the stack here. subtraction = rsp_alignment & 0xF; } subtraction += 0x10 * xmm_count; - size_t xmm_base_subtraction = subtraction; + std::size_t xmm_base_subtraction = subtraction; subtraction += needed_frame_size; subtraction += ABI_SHADOW_SPACE; // Final alignment. @@ -173,8 +174,9 @@ inline void ABI_CalculateFrameSize(BitSet32 regs, size_t rsp_alignment, size_t n *out_xmm_offset = (s32)(subtraction - xmm_base_subtraction); } -inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, - size_t rsp_alignment, size_t needed_frame_size = 0) { +inline std::size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, + std::size_t rsp_alignment, + std::size_t needed_frame_size = 0) { s32 subtraction, xmm_offset; ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset); @@ -195,7 +197,8 @@ inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet } inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, - size_t rsp_alignment, size_t needed_frame_size = 0) { + std::size_t rsp_alignment, + std::size_t needed_frame_size = 0) { s32 subtraction, xmm_offset; ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset); diff --git a/src/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h index 02323a017..5cc8a8c76 100644 --- a/src/common/x64/xbyak_util.h +++ b/src/common/x64/xbyak_util.h @@ -34,7 +34,7 @@ inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) { template <typename T> inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) { static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer."); - size_t addr = reinterpret_cast<size_t>(f); + std::size_t addr = reinterpret_cast<std::size_t>(f); if (IsWithin2G(code, addr)) { code.call(f); } else { |