From 590307b94c5865c0a75a18e9a593d251ce38407a Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 27 Feb 2018 19:38:00 +1000 Subject: [PATCH] ShaderCache: Use memcmp for comparing pipeline UIDs As these are stored in a map, operator< will become a hot function when doing lookups, which happen every frame. std::tie generated a rather large function here with quite a few branches. --- Source/Core/VideoCommon/ShaderCache.h | 38 ++++++++++++--------- Source/Core/VideoCommon/VertexManagerBase.h | 4 +-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Source/Core/VideoCommon/ShaderCache.h b/Source/Core/VideoCommon/ShaderCache.h index 922cd4d5fa..6516edd8d8 100644 --- a/Source/Core/VideoCommon/ShaderCache.h +++ b/Source/Core/VideoCommon/ShaderCache.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -42,19 +43,23 @@ struct GXPipelineConfig DepthState depth_state; BlendingState blending_state; + // We use memcmp() for comparing pipelines as std::tie generates a large number of instructions, + // and this map lookup can happen every draw call. However, as using memcmp() will also compare + // any padding bytes, we have to ensure these are zeroed out. + GXPipelineConfig() { std::memset(this, 0, sizeof(*this)); } + GXPipelineConfig(const GXPipelineConfig& rhs) { std::memcpy(this, &rhs, sizeof(*this)); } + GXPipelineConfig& operator=(const GXPipelineConfig& rhs) + { + std::memcpy(this, &rhs, sizeof(*this)); + return *this; + } bool operator<(const GXPipelineConfig& rhs) const { - return std::tie(vertex_format, vs_uid, gs_uid, ps_uid, rasterization_state.hex, depth_state.hex, - blending_state.hex) < std::tie(rhs.vertex_format, rhs.vs_uid, rhs.gs_uid, - rhs.ps_uid, rhs.rasterization_state.hex, - rhs.depth_state.hex, rhs.blending_state.hex); + return std::memcmp(this, &rhs, sizeof(*this)) < 0; } bool operator==(const GXPipelineConfig& rhs) const { - return std::tie(vertex_format, vs_uid, gs_uid, ps_uid, rasterization_state.hex, depth_state.hex, - blending_state.hex) == std::tie(rhs.vertex_format, rhs.vs_uid, rhs.gs_uid, - rhs.ps_uid, rhs.rasterization_state.hex, - rhs.depth_state.hex, rhs.blending_state.hex); + return std::memcmp(this, &rhs, sizeof(*this)) == 0; } bool operator!=(const GXPipelineConfig& rhs) const { return !operator==(rhs); } }; @@ -68,19 +73,20 @@ struct GXUberPipelineConfig DepthState depth_state; BlendingState blending_state; + GXUberPipelineConfig() { std::memset(this, 0, sizeof(*this)); } + GXUberPipelineConfig(const GXUberPipelineConfig& rhs) { std::memcpy(this, &rhs, sizeof(*this)); } + GXUberPipelineConfig& operator=(const GXUberPipelineConfig& rhs) + { + std::memcpy(this, &rhs, sizeof(*this)); + return *this; + } bool operator<(const GXUberPipelineConfig& rhs) const { - return std::tie(vertex_format, vs_uid, gs_uid, ps_uid, rasterization_state.hex, depth_state.hex, - blending_state.hex) < std::tie(rhs.vertex_format, rhs.vs_uid, rhs.gs_uid, - rhs.ps_uid, rhs.rasterization_state.hex, - rhs.depth_state.hex, rhs.blending_state.hex); + return std::memcmp(this, &rhs, sizeof(*this)) < 0; } bool operator==(const GXUberPipelineConfig& rhs) const { - return std::tie(vertex_format, vs_uid, gs_uid, ps_uid, rasterization_state.hex, depth_state.hex, - blending_state.hex) == std::tie(rhs.vertex_format, rhs.vs_uid, rhs.gs_uid, - rhs.ps_uid, rhs.rasterization_state.hex, - rhs.depth_state.hex, rhs.blending_state.hex); + return std::memcmp(this, &rhs, sizeof(*this)) == 0; } bool operator!=(const GXUberPipelineConfig& rhs) const { return !operator==(rhs); } }; diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h index 20a63a3e2a..eac95f614f 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.h +++ b/Source/Core/VideoCommon/VertexManagerBase.h @@ -83,8 +83,8 @@ protected: Slope m_zslope = {}; void CalculateZSlope(NativeVertexFormat* format); - VideoCommon::GXPipelineConfig m_current_pipeline_config = {}; - VideoCommon::GXUberPipelineConfig m_current_uber_pipeline_config = {}; + VideoCommon::GXPipelineConfig m_current_pipeline_config; + VideoCommon::GXUberPipelineConfig m_current_uber_pipeline_config; const AbstractPipeline* m_current_pipeline_object = nullptr; PrimitiveType m_current_primitive_type = PrimitiveType::Points; bool m_pipeline_config_changed = true;