citra-emu
/
citra
Archived
1
0
Fork 0

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
1 changed files with 24 additions and 22 deletions

View File

@ -106,15 +106,17 @@ ShaderDiskCache::ShaderDiskCache(bool separable) : separable{separable} {}
std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable() {
const bool has_title_id = GetProgramID() != 0;
if (!Settings::values.use_hw_shader || !Settings::values.use_disk_shader_cache || !has_title_id)
return {};
if (!Settings::values.use_hw_shader || !Settings::values.use_disk_shader_cache ||
!has_title_id) {
return std::nullopt;
}
tried_to_load = true;
FileUtil::IOFile file(GetTransferablePath(), "rb");
if (!file.IsOpen()) {
LOG_INFO(Render_OpenGL, "No transferable shader cache found for game with title id={}",
GetTitleID());
return {};
return std::nullopt;
}
u32 version{};
@ -122,19 +124,19 @@ std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable
LOG_ERROR(Render_OpenGL,
"Failed to get transferable cache version for title id={} - skipping",
GetTitleID());
return {};
return std::nullopt;
}
if (version < NativeVersion) {
LOG_INFO(Render_OpenGL, "Transferable shader cache is old - removing");
file.Close();
InvalidateAll();
return {};
return std::nullopt;
}
if (version > NativeVersion) {
LOG_WARNING(Render_OpenGL, "Transferable shader cache was generated with a newer version "
"of the emulator - skipping");
return {};
return std::nullopt;
}
// Version is valid, load the shaders
@ -143,7 +145,7 @@ std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable
TransferableEntryKind kind{};
if (file.ReadBytes(&kind, sizeof(u32)) != sizeof(u32)) {
LOG_ERROR(Render_OpenGL, "Failed to read transferable file - skipping");
return {};
return std::nullopt;
}
switch (kind) {
@ -151,7 +153,7 @@ std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable
ShaderDiskCacheRaw entry;
if (!entry.Load(file)) {
LOG_ERROR(Render_OpenGL, "Failed to load transferable raw entry - skipping");
return {};
return std::nullopt;
}
transferable.emplace(entry.GetUniqueIdentifier(), ShaderDiskCacheRaw{});
raws.push_back(std::move(entry));
@ -160,7 +162,7 @@ std::optional<std::vector<ShaderDiskCacheRaw>> ShaderDiskCache::LoadTransferable
default:
LOG_ERROR(Render_OpenGL, "Unknown transferable shader cache entry kind={} - skipping",
static_cast<u32>(kind));
return {};
return std::nullopt;
}
}
@ -203,11 +205,11 @@ ShaderDiskCache::LoadPrecompiledFile(FileUtil::IOFile& file) {
ShaderCacheVersionHash file_hash{};
if (!LoadArrayFromPrecompiled(file_hash.data(), file_hash.size())) {
return {};
return std::nullopt;
}
if (GetShaderCacheVersionHash() != file_hash) {
LOG_INFO(Render_OpenGL, "Precompiled cache is from another version of the emulator");
return {};
return std::nullopt;
}
std::unordered_map<u64, ShaderDiskCacheDecompiled> decompiled;
@ -215,19 +217,19 @@ ShaderDiskCache::LoadPrecompiledFile(FileUtil::IOFile& file) {
while (decompressed_precompiled_cache_offset < decompressed_precompiled_cache.size()) {
PrecompiledEntryKind kind{};
if (!LoadObjectFromPrecompiled(kind)) {
return {};
return std::nullopt;
}
switch (kind) {
case PrecompiledEntryKind::Decompiled: {
u64 unique_identifier{};
if (!LoadObjectFromPrecompiled(unique_identifier)) {
return {};
return std::nullopt;
}
auto entry = LoadDecompiledEntry();
if (!entry) {
return {};
return std::nullopt;
}
decompiled.insert({unique_identifier, std::move(*entry)});
break;
@ -235,29 +237,29 @@ ShaderDiskCache::LoadPrecompiledFile(FileUtil::IOFile& file) {
case PrecompiledEntryKind::Dump: {
u64 unique_identifier;
if (!LoadObjectFromPrecompiled(unique_identifier)) {
return {};
return std::nullopt;
}
ShaderDiskCacheDump dump;
if (!LoadObjectFromPrecompiled(dump.binary_format)) {
return {};
return std::nullopt;
}
u32 binary_length{};
if (!LoadObjectFromPrecompiled(binary_length)) {
return {};
return std::nullopt;
}
dump.binary.resize(binary_length);
if (!LoadArrayFromPrecompiled(dump.binary.data(), dump.binary.size())) {
return {};
return std::nullopt;
}
dumps.insert({unique_identifier, dump});
break;
}
default:
return {};
return std::nullopt;
}
}
@ -271,17 +273,17 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCache::LoadDecompiledEntry()
bool sanitize_mul;
if (!LoadObjectFromPrecompiled(sanitize_mul)) {
return {};
return std::nullopt;
}
u32 code_size{};
if (!LoadObjectFromPrecompiled(code_size)) {
return {};
return std::nullopt;
}
std::string code(code_size, '\0');
if (!LoadArrayFromPrecompiled(code.data(), code.size())) {
return {};
return std::nullopt;
}
ShaderDiskCacheDecompiled entry;