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:
Mat M 2020-04-30 23:42:32 -04:00 committed by GitHub
parent 4a677e83fe
commit 85d37c9994
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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;