mirror of
https://github.com/thejerf/baijiSteamVR.git
synced 2026-10-26 18:02:27 +01:00
280 lines
9.5 KiB
C++
280 lines
9.5 KiB
C++
// Copyright 2026 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "VideoCommon/ShaderHunter.h"
|
|
|
|
class ElementsGroupManager
|
|
{
|
|
public:
|
|
using RuntimeElementSignature = ShaderHunter::RuntimeElementSignature;
|
|
using ShaderType = ShaderHunter::ShaderType;
|
|
using HandlingType = ShaderHunter::HandlingType;
|
|
using HuntingOption = ShaderHunter::HuntingOption;
|
|
|
|
enum class PreviewAction
|
|
{
|
|
None = 0,
|
|
Skip = 1,
|
|
Pink = 2
|
|
};
|
|
|
|
struct DrawRecord
|
|
{
|
|
int draw_index = -1;
|
|
u32 draw_sequence = 0;
|
|
u64 vs_hash = 0;
|
|
u64 ps_hash = 0;
|
|
u64 gs_hash = 0;
|
|
u64 vs_family = 0;
|
|
u64 ps_family = 0;
|
|
u64 gs_family = 0;
|
|
RuntimeElementSignature signature;
|
|
std::array<u64, 8> textures{};
|
|
std::array<std::string, 8> texture_names{};
|
|
|
|
u64 GetHash(ShaderType type) const;
|
|
u64 GetFamily(ShaderType type) const;
|
|
};
|
|
|
|
struct StableSubMatchSignature
|
|
{
|
|
RuntimeElementSignature runtime_element;
|
|
u64 vs_family = 0;
|
|
u64 ps_family = 0;
|
|
u64 gs_family = 0;
|
|
std::vector<u64> texture_hashes;
|
|
int occurrence_slot = -1;
|
|
};
|
|
|
|
struct SelectedSubgroupSignature
|
|
{
|
|
u64 vs_family = 0;
|
|
u64 ps_family = 0;
|
|
u64 gs_family = 0;
|
|
std::vector<u64> texture_hashes;
|
|
};
|
|
|
|
struct CurrentMatchCandidate
|
|
{
|
|
SelectedSubgroupSignature subgroup;
|
|
DrawRecord representative_draw;
|
|
int raw_draw_count = 0;
|
|
bool active_this_frame = false;
|
|
};
|
|
|
|
struct ElementGroupOverride
|
|
{
|
|
std::string name;
|
|
std::string comments;
|
|
std::string credits;
|
|
HandlingType handling = HandlingType::Skip;
|
|
RuntimeElementSignature runtime_element;
|
|
int layer = -1;
|
|
float element_depth = -1.0f;
|
|
float units_per_meter = -1.0f;
|
|
int element_start = -1;
|
|
int element_end = -1;
|
|
int element_reference_total = 0;
|
|
std::vector<u64> texture_hashes;
|
|
bool texture_hashes_excluded = false;
|
|
std::vector<SelectedSubgroupSignature> selected_match_filter;
|
|
bool selected_match_filter_excluded = false;
|
|
bool refinement_enabled = false;
|
|
ShaderType refinement_type = ShaderType::Pixel;
|
|
u64 refinement_hash = 0;
|
|
bool refinement_family_match = false;
|
|
u64 refinement_family_signature = 0;
|
|
bool enabled = true;
|
|
bool user_defined = true;
|
|
std::string flag_group;
|
|
std::string condition_flag;
|
|
bool condition_inverted = false;
|
|
};
|
|
|
|
struct SeedCandidate
|
|
{
|
|
RuntimeElementSignature signature;
|
|
RuntimeElementSignature group_signature;
|
|
DrawRecord representative_draw;
|
|
int occurrence_count = 0;
|
|
};
|
|
|
|
struct Status
|
|
{
|
|
bool popup_open = false;
|
|
bool hunt_enabled = false;
|
|
HuntingOption option = HuntingOption::Skip;
|
|
bool seed_valid = false;
|
|
RuntimeElementSignature seed_signature;
|
|
std::optional<DrawRecord> seed_draw;
|
|
int selected_seed_index = -1;
|
|
int total_seed_candidates = 0;
|
|
int selected_match = 0;
|
|
int total_matches = 0;
|
|
int active_matches = 0;
|
|
int selected_match_filter_count = 0;
|
|
bool selected_match_filter_excluded = false;
|
|
int highlighted_match_raw_draw_count = 0;
|
|
std::optional<DrawRecord> highlighted_draw;
|
|
};
|
|
|
|
static ElementsGroupManager& GetInstance();
|
|
|
|
static std::vector<ElementGroupOverride> LoadOverridesFromINI(
|
|
const std::string& game_id, std::optional<u16> revision = std::nullopt);
|
|
static void SaveOverridesToINI(const std::string& game_id,
|
|
const std::vector<ElementGroupOverride>& overrides);
|
|
static RuntimeElementSignature MakeSelectedMatchFilterSignature(
|
|
const RuntimeElementSignature& signature);
|
|
static StableSubMatchSignature MakeStableSubMatchSignature(const DrawRecord& draw,
|
|
int occurrence_slot);
|
|
static SelectedSubgroupSignature MakeSelectedSubgroupSignature(const DrawRecord& draw);
|
|
|
|
void LoadOverrides(const std::string& game_id);
|
|
void LoadOverridesIfNeeded(const std::string& game_id);
|
|
bool HasOverrides() const;
|
|
|
|
void SetPopupOpen(bool open);
|
|
bool IsPopupOpen() const;
|
|
void SetHuntEnabled(bool enabled);
|
|
bool IsHuntEnabled() const;
|
|
void SetHuntingOption(HuntingOption option);
|
|
HuntingOption GetHuntingOption() const;
|
|
|
|
void SelectSeedCandidate(int index);
|
|
void SetSeedGroupMask(bool projection, bool layer, bool viewport, bool scissor,
|
|
bool render_state);
|
|
void SelectMatch(int index);
|
|
void NextMatch();
|
|
void PrevMatch();
|
|
|
|
std::vector<SeedCandidate> GetSeedCandidates() const;
|
|
std::vector<CurrentMatchCandidate> GetCurrentMatches() const;
|
|
std::vector<SelectedSubgroupSignature> GetSelectedMatchFilters() const;
|
|
bool GetSelectedMatchFilterExcluded() const;
|
|
std::vector<CurrentMatchCandidate> GetSelectedMatchDisplayDraws() const;
|
|
std::vector<DrawRecord> GetCurrentTextureSourceDraws() const;
|
|
std::optional<DrawRecord> GetHighlightedDraw() const;
|
|
std::optional<DrawRecord> GetSelectedSeedDraw() const;
|
|
std::optional<DrawRecord> GetSelectedCurrentMatchDraw() const;
|
|
std::optional<DrawRecord> GetCurrentTextureSourceDraw() const;
|
|
RuntimeElementSignature GetSeedSignature() const;
|
|
Status GetStatus() const;
|
|
bool IsCurrentMatchFilterEnabled(int match_index) const;
|
|
void SetSelectedMatchFilterExcluded(bool excluded);
|
|
void SetCurrentMatchFilterEnabled(int match_index, bool enabled);
|
|
void AddCurrentMatchFilter();
|
|
void RemoveSelectedMatchFilter(int index);
|
|
|
|
PreviewAction RegisterDraw(const DrawRecord& draw);
|
|
void OnFrameEnd();
|
|
|
|
void AdvanceOverrideDrawCounters(const DrawRecord& draw);
|
|
void RegisterFlagsForDraw(const DrawRecord& draw);
|
|
bool ShouldSkipByOverride(const DrawRecord& draw) const;
|
|
HandlingType GetOverrideHandling(const DrawRecord& draw) const;
|
|
int GetOverrideLayer(const DrawRecord& draw) const;
|
|
float GetOverrideElementDepth(const DrawRecord& draw) const;
|
|
float GetOverrideUnitsPerMeter(const DrawRecord& draw) const;
|
|
|
|
private:
|
|
ElementsGroupManager() = default;
|
|
|
|
struct CounterKey
|
|
{
|
|
u64 value = 0;
|
|
|
|
bool operator==(const CounterKey& other) const
|
|
{
|
|
return value == other.value;
|
|
}
|
|
};
|
|
|
|
struct CounterKeyHasher
|
|
{
|
|
size_t operator()(const CounterKey& key) const noexcept;
|
|
};
|
|
|
|
struct StableSubMatchContext
|
|
{
|
|
bool valid = false;
|
|
u32 draw_sequence = 0;
|
|
StableSubMatchSignature signature;
|
|
};
|
|
|
|
struct GroupMask
|
|
{
|
|
bool projection = false;
|
|
bool layer = false;
|
|
bool viewport = false;
|
|
bool scissor = false;
|
|
bool render_state = false;
|
|
};
|
|
|
|
void ClearSeedSelectionLocked();
|
|
void SelectSeedCandidateLocked(int index);
|
|
bool HasActiveHuntLocked() const;
|
|
RuntimeElementSignature GetMaskedSeedSignatureLocked() const;
|
|
RuntimeElementSignature GetSeedGroupSignatureLocked(const RuntimeElementSignature& signature) const;
|
|
bool MatchesSelectedMatchFilterLocked(const DrawRecord& draw) const;
|
|
bool MatchesSelectedMatchFilterSignatureLocked(const SelectedSubgroupSignature& signature) const;
|
|
std::vector<CurrentMatchCandidate> ResolveSelectedMatchDisplayDrawsLocked() const;
|
|
StableSubMatchSignature GetStableSubMatchSignatureLocked(const DrawRecord& draw) const;
|
|
std::pair<int, int> ResolveElementRange(const ElementGroupOverride& entry,
|
|
const DrawRecord& draw) const;
|
|
bool DoesEntryMatchForRange(const ElementGroupOverride& entry, const DrawRecord& draw) const;
|
|
bool DoesSelectedMatchFilterPass(const ElementGroupOverride& entry, const DrawRecord& draw) const;
|
|
bool DoesOptionalRefinementPass(const ElementGroupOverride& entry, const DrawRecord& draw) const;
|
|
bool DoesEntryMatch(const ElementGroupOverride& entry, const DrawRecord& draw,
|
|
bool include_condition) const;
|
|
bool DoesTextureFilterPass(const DrawRecord& draw, const ElementGroupOverride& entry) const;
|
|
CounterKey GetCounterKey(const ElementGroupOverride& entry) const;
|
|
|
|
mutable std::mutex m_mutex;
|
|
int m_popup_open_count = 0;
|
|
std::atomic_bool m_popup_open = false;
|
|
std::atomic_bool m_has_overrides = false;
|
|
bool m_hunt_enabled = false;
|
|
HuntingOption m_hunting_option = HuntingOption::Skip;
|
|
RuntimeElementSignature m_seed_signature{};
|
|
RuntimeElementSignature m_seed_group_signature{};
|
|
std::optional<DrawRecord> m_seed_draw;
|
|
GroupMask m_group_mask;
|
|
int m_selected_seed_index = -1;
|
|
int m_selected_match = 0;
|
|
std::vector<SelectedSubgroupSignature> m_selected_match_filters;
|
|
bool m_selected_match_filters_excluded = false;
|
|
|
|
std::vector<DrawRecord> m_collecting_draws;
|
|
std::vector<DrawRecord> m_display_draws;
|
|
std::vector<SeedCandidate> m_display_seed_candidates;
|
|
std::vector<DrawRecord> m_collecting_matches;
|
|
std::vector<DrawRecord> m_display_raw_matches;
|
|
std::vector<SelectedSubgroupSignature> m_display_raw_match_signatures;
|
|
std::vector<CurrentMatchCandidate> m_display_matches;
|
|
int m_collecting_match_total = 0;
|
|
int m_display_match_total = 0;
|
|
std::optional<DrawRecord> m_collecting_highlighted_draw;
|
|
std::optional<DrawRecord> m_display_highlighted_draw;
|
|
int m_display_highlighted_match_raw_draw_count = 0;
|
|
|
|
std::vector<ElementGroupOverride> m_overrides;
|
|
std::string m_loaded_game_id;
|
|
|
|
mutable std::unordered_map<CounterKey, int, CounterKeyHasher> m_draw_counters;
|
|
mutable std::unordered_map<CounterKey, int, CounterKeyHasher> m_draw_totals_prev;
|
|
mutable std::unordered_map<CounterKey, int, CounterKeyHasher> m_current_draw_indices;
|
|
mutable std::unordered_map<u64, int> m_stable_submatch_occurrence_counters;
|
|
mutable StableSubMatchContext m_current_stable_submatch;
|
|
};
|