From 85d37c99943817e3f41346127c3633ad59a8b716 Mon Sep 17 00:00:00 2001 From: Mat M Date: Thu, 30 Apr 2020 23:42:32 -0400 Subject: [PATCH] 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> 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. --- .../renderer_opengl/gl_shader_disk_cache.cpp | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 501f4c7d5..432421160 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp @@ -106,15 +106,17 @@ ShaderDiskCache::ShaderDiskCache(bool separable) : separable{separable} {} std::optional> 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> 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> 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> 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> ShaderDiskCache::LoadTransferable default: LOG_ERROR(Render_OpenGL, "Unknown transferable shader cache entry kind={} - skipping", static_cast(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 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 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;