gl_shader_disk: Make use of std::nullopt where applicable (#5293)
Some implementations can use the std::nullopt_t constructor of std::optional to avoid needing to completely zero out the internal buffer of the optional and instead only set the validity byte within it. e.g. Consider the following function: std::optional<std::vector<ShaderDiskCacheRaw>> fn() { return {}; } With libc++ this will result in the following code generation on x86-64: Fn(): mov rax, rdi vxorps xmm0, xmm0, xmm0 vmovups ymmword ptr [rdi], ymm0 vzeroupper ret With libstdc++, we also get the similar equivalent: Fn(): vpxor xmm0, xmm0, xmm0 mov rax, rdi vmovdqu XMMWORD PTR [rdi], xmm0 vmovdqu XMMWORD PTR [rdi+16], xmm0 ret If we change this function to return std::nullopt instead, then this simplifies both the code gen from libc++ and libstdc++ down to: Fn(): mov BYTE PTR [rdi+24], 0 mov rax, rdi ret Given how little of a change is necessary to result in better code generation, this is essentially a "free" very minor optimization.
This commit is contained in:
parent
4a677e83fe
commit
85d37c9994
|
@ -106,15 +106,17 @@ ShaderDiskCache::ShaderDiskCache(bool separable) : separable{separable} {}
|
||||||
|
|
||||||
std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable() {
|
std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable() {
|
||||||
const bool has_title_id = GetProgramID() != 0;
|
const bool has_title_id = GetProgramID() != 0;
|
||||||
if (!Settings::values.use_hw_shader || !Settings::values.use_disk_shader_cache || !has_title_id)
|
if (!Settings::values.use_hw_shader || !Settings::values.use_disk_shader_cache ||
|
||||||
return {};
|
!has_title_id) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
tried_to_load = true;
|
tried_to_load = true;
|
||||||
|
|
||||||
FileUtil::IOFile file(GetTransferablePath(), "rb");
|
FileUtil::IOFile file(GetTransferablePath(), "rb");
|
||||||
if (!file.IsOpen()) {
|
if (!file.IsOpen()) {
|
||||||
LOG_INFO(Render_OpenGL, "No transferable shader cache found for game with title id={}",
|
LOG_INFO(Render_OpenGL, "No transferable shader cache found for game with title id={}",
|
||||||
GetTitleID());
|
GetTitleID());
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 version{};
|
u32 version{};
|
||||||
|
@ -122,19 +124,19 @@ std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable
|
||||||
LOG_ERROR(Render_OpenGL,
|
LOG_ERROR(Render_OpenGL,
|
||||||
"Failed to get transferable cache version for title id={} - skipping",
|
"Failed to get transferable cache version for title id={} - skipping",
|
||||||
GetTitleID());
|
GetTitleID());
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version < NativeVersion) {
|
if (version < NativeVersion) {
|
||||||
LOG_INFO(Render_OpenGL, "Transferable shader cache is old - removing");
|
LOG_INFO(Render_OpenGL, "Transferable shader cache is old - removing");
|
||||||
file.Close();
|
file.Close();
|
||||||
InvalidateAll();
|
InvalidateAll();
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
if (version > NativeVersion) {
|
if (version > NativeVersion) {
|
||||||
LOG_WARNING(Render_OpenGL, "Transferable shader cache was generated with a newer version "
|
LOG_WARNING(Render_OpenGL, "Transferable shader cache was generated with a newer version "
|
||||||
"of the emulator - skipping");
|
"of the emulator - skipping");
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version is valid, load the shaders
|
// Version is valid, load the shaders
|
||||||
|
@ -143,7 +145,7 @@ std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable
|
||||||
TransferableEntryKind kind{};
|
TransferableEntryKind kind{};
|
||||||
if (file.ReadBytes(&kind, sizeof(u32)) != sizeof(u32)) {
|
if (file.ReadBytes(&kind, sizeof(u32)) != sizeof(u32)) {
|
||||||
LOG_ERROR(Render_OpenGL, "Failed to read transferable file - skipping");
|
LOG_ERROR(Render_OpenGL, "Failed to read transferable file - skipping");
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
@ -151,7 +153,7 @@ std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable
|
||||||
ShaderDiskCacheRaw entry;
|
ShaderDiskCacheRaw entry;
|
||||||
if (!entry.Load(file)) {
|
if (!entry.Load(file)) {
|
||||||
LOG_ERROR(Render_OpenGL, "Failed to load transferable raw entry - skipping");
|
LOG_ERROR(Render_OpenGL, "Failed to load transferable raw entry - skipping");
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
transferable.emplace(entry.GetUniqueIdentifier(), ShaderDiskCacheRaw{});
|
transferable.emplace(entry.GetUniqueIdentifier(), ShaderDiskCacheRaw{});
|
||||||
raws.push_back(std::move(entry));
|
raws.push_back(std::move(entry));
|
||||||
|
@ -160,7 +162,7 @@ std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Render_OpenGL, "Unknown transferable shader cache entry kind={} - skipping",
|
LOG_ERROR(Render_OpenGL, "Unknown transferable shader cache entry kind={} - skipping",
|
||||||
static_cast<u32>(kind));
|
static_cast<u32>(kind));
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,11 +205,11 @@ ShaderDiskCache::LoadPrecompiledFile(FileUtil::IOFile& file) {
|
||||||
|
|
||||||
ShaderCacheVersionHash file_hash{};
|
ShaderCacheVersionHash file_hash{};
|
||||||
if (!LoadArrayFromPrecompiled(file_hash.data(), file_hash.size())) {
|
if (!LoadArrayFromPrecompiled(file_hash.data(), file_hash.size())) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
if (GetShaderCacheVersionHash() != file_hash) {
|
if (GetShaderCacheVersionHash() != file_hash) {
|
||||||
LOG_INFO(Render_OpenGL, "Precompiled cache is from another version of the emulator");
|
LOG_INFO(Render_OpenGL, "Precompiled cache is from another version of the emulator");
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<u64, ShaderDiskCacheDecompiled> decompiled;
|
std::unordered_map<u64, ShaderDiskCacheDecompiled> decompiled;
|
||||||
|
@ -215,19 +217,19 @@ ShaderDiskCache::LoadPrecompiledFile(FileUtil::IOFile& file) {
|
||||||
while (decompressed_precompiled_cache_offset < decompressed_precompiled_cache.size()) {
|
while (decompressed_precompiled_cache_offset < decompressed_precompiled_cache.size()) {
|
||||||
PrecompiledEntryKind kind{};
|
PrecompiledEntryKind kind{};
|
||||||
if (!LoadObjectFromPrecompiled(kind)) {
|
if (!LoadObjectFromPrecompiled(kind)) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case PrecompiledEntryKind::Decompiled: {
|
case PrecompiledEntryKind::Decompiled: {
|
||||||
u64 unique_identifier{};
|
u64 unique_identifier{};
|
||||||
if (!LoadObjectFromPrecompiled(unique_identifier)) {
|
if (!LoadObjectFromPrecompiled(unique_identifier)) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto entry = LoadDecompiledEntry();
|
auto entry = LoadDecompiledEntry();
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
decompiled.insert({unique_identifier, std::move(*entry)});
|
decompiled.insert({unique_identifier, std::move(*entry)});
|
||||||
break;
|
break;
|
||||||
|
@ -235,29 +237,29 @@ ShaderDiskCache::LoadPrecompiledFile(FileUtil::IOFile& file) {
|
||||||
case PrecompiledEntryKind::Dump: {
|
case PrecompiledEntryKind::Dump: {
|
||||||
u64 unique_identifier;
|
u64 unique_identifier;
|
||||||
if (!LoadObjectFromPrecompiled(unique_identifier)) {
|
if (!LoadObjectFromPrecompiled(unique_identifier)) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderDiskCacheDump dump;
|
ShaderDiskCacheDump dump;
|
||||||
if (!LoadObjectFromPrecompiled(dump.binary_format)) {
|
if (!LoadObjectFromPrecompiled(dump.binary_format)) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 binary_length{};
|
u32 binary_length{};
|
||||||
if (!LoadObjectFromPrecompiled(binary_length)) {
|
if (!LoadObjectFromPrecompiled(binary_length)) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
dump.binary.resize(binary_length);
|
dump.binary.resize(binary_length);
|
||||||
if (!LoadArrayFromPrecompiled(dump.binary.data(), dump.binary.size())) {
|
if (!LoadArrayFromPrecompiled(dump.binary.data(), dump.binary.size())) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
dumps.insert({unique_identifier, dump});
|
dumps.insert({unique_identifier, dump});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,17 +273,17 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCache::LoadDecompiledEntry()
|
||||||
|
|
||||||
bool sanitize_mul;
|
bool sanitize_mul;
|
||||||
if (!LoadObjectFromPrecompiled(sanitize_mul)) {
|
if (!LoadObjectFromPrecompiled(sanitize_mul)) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 code_size{};
|
u32 code_size{};
|
||||||
if (!LoadObjectFromPrecompiled(code_size)) {
|
if (!LoadObjectFromPrecompiled(code_size)) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string code(code_size, '\0');
|
std::string code(code_size, '\0');
|
||||||
if (!LoadArrayFromPrecompiled(code.data(), code.size())) {
|
if (!LoadArrayFromPrecompiled(code.data(), code.size())) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderDiskCacheDecompiled entry;
|
ShaderDiskCacheDecompiled entry;
|
||||||
|
|
Reference in New Issue