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.
This commit is contained in:
Stenzek 2018-02-27 19:38:00 +10:00
parent 41296db083
commit 590307b94c
2 changed files with 24 additions and 18 deletions

View File

@ -6,6 +6,7 @@
#include <array>
#include <cstddef>
#include <cstring>
#include <map>
#include <memory>
#include <optional>
@ -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); }
};

View File

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