From 595af125b9c4d836809edbdfc4356e7d1e5ac52f Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 13 Aug 2022 20:50:40 +0200 Subject: [PATCH] Load state maps when loading techniques --- .../AssetLoaders/AssetLoaderTechniqueSet.cpp | 63 +++++++++++++++++-- .../AssetLoaders/AssetLoaderTechniqueSet.h | 4 ++ .../StateMap/Parsing/StateMapParser.cpp | 4 +- .../StateMap/Parsing/StateMapParser.h | 2 +- .../StateMap/Parsing/StateMapParserState.cpp | 7 ++- .../StateMap/Parsing/StateMapParserState.h | 2 +- .../StateMap/StateMapDefinition.cpp | 5 +- src/ObjLoading/StateMap/StateMapDefinition.h | 4 +- src/ObjLoading/StateMap/StateMapReader.cpp | 7 ++- src/ObjLoading/StateMap/StateMapReader.h | 3 +- .../Sequence/TechniquePassScopeSequences.cpp | 15 +++-- .../Techset/TechniqueDefinitionAcceptor.h | 2 +- .../Techset/TechniqueStateMapCache.cpp | 30 +++++++++ .../Techset/TechniqueStateMapCache.h | 22 ++++++- 14 files changed, 142 insertions(+), 28 deletions(-) diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp index d555c112..d09192f9 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp @@ -17,6 +17,8 @@ #include "Techset/TechniqueFileReader.h" #include "Techset/TechsetFileReader.h" #include "Shader/D3D9ShaderAnalyser.h" +#include "StateMap/StateMapReader.h" +#include "Techset/TechniqueStateMapCache.h" #include "Techset/TechsetDefinitionCache.h" #include "Utils/Alignment.h" @@ -118,10 +120,12 @@ namespace IW4 class TechniqueCreator final : public techset::ITechniqueDefinitionAcceptor { + const std::string& m_technique_name; ISearchPath* const m_search_path; MemoryManager* const m_memory; IAssetLoadingManager* const m_manager; TechniqueZoneLoadingState* const m_zone_state; + techset::TechniqueStateMapCache* const m_state_map_cache; ShaderInfoFromFileSystemCacheState* const m_shader_info_cache; public: @@ -201,11 +205,15 @@ namespace IW4 std::vector m_passes; std::vector m_dependencies; - TechniqueCreator(ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, TechniqueZoneLoadingState* zoneState, ShaderInfoFromFileSystemCacheState* shaderInfoCache) - : m_search_path(searchPath), + TechniqueCreator(const std::string& techniqueName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, TechniqueZoneLoadingState* zoneState, + ShaderInfoFromFileSystemCacheState* shaderInfoCache, + techset::TechniqueStateMapCache* stateMapCache) + : m_technique_name(techniqueName), + m_search_path(searchPath), m_memory(memory), m_manager(manager), m_zone_state(zoneState), + m_state_map_cache(stateMapCache), m_shader_info_cache(shaderInfoCache) { } @@ -406,9 +414,20 @@ namespace IW4 return true; } - void AcceptStateMap(const std::string& stateMapName) override + bool AcceptStateMap(const std::string& stateMapName, std::string& errorMessage) override { - // TODO: State maps currently are not used + const auto* stateMap = AssetLoaderTechniqueSet::LoadStateMapDefinition(stateMapName, m_search_path, m_state_map_cache); + + if (!stateMap) + { + std::ostringstream ss; + ss << "Failed to load specified state map \"" << stateMapName << "\""; + errorMessage = ss.str(); + return false; + } + + m_state_map_cache->SetTechniqueUsesStateMap(m_technique_name, stateMap); + return true; } static void InitializeArgumentState(const d3d9::ShaderInfo& shaderInfo, std::vector& argumentHandledOffsetVector, std::vector& argumentHandledVector) @@ -986,6 +1005,7 @@ namespace IW4 IAssetLoadingManager* m_manager; TechniqueZoneLoadingState* m_zone_state; ShaderInfoFromFileSystemCacheState* m_shader_info_cache; + techset::TechniqueStateMapCache* m_state_map_cache; static std::string GetTechniqueFileName(const std::string& techniqueName) { @@ -1185,7 +1205,7 @@ namespace IW4 if (!file.IsOpen()) return nullptr; - TechniqueCreator creator(m_search_path, m_memory, m_manager, m_zone_state, m_shader_info_cache); + TechniqueCreator creator(techniqueName, m_search_path, m_memory, m_manager, m_zone_state, m_shader_info_cache, m_state_map_cache); const techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator); if (!reader.ReadTechniqueDefinition()) return nullptr; @@ -1199,7 +1219,8 @@ namespace IW4 m_memory(memory), m_manager(manager), m_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()), - m_shader_info_cache(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()) + m_shader_info_cache(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()), + m_state_map_cache(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()) { } @@ -1234,6 +1255,13 @@ std::string AssetLoaderTechniqueSet::GetTechsetFileName(const std::string& techs return ss.str(); } +std::string AssetLoaderTechniqueSet::GetStateMapFileName(const std::string& stateMapName) +{ + std::ostringstream ss; + ss << "statemaps/" << stateMapName << ".sm"; + return ss.str(); +} + bool AssetLoaderTechniqueSet::CreateTechsetFromDefinition(const std::string& assetName, const techset::TechsetDefinition& definition, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) { @@ -1285,6 +1313,29 @@ techset::TechsetDefinition* AssetLoaderTechniqueSet::LoadTechsetDefinition(const return techsetDefinitionPtr; } +const state_map::StateMapDefinition* AssetLoaderTechniqueSet::LoadStateMapDefinition(const std::string& stateMapName, ISearchPath* searchPath, techset::TechniqueStateMapCache* stateMapCache) +{ + auto* cachedStateMap = stateMapCache->GetCachedStateMap(stateMapName); + if (cachedStateMap) + return cachedStateMap; + + const auto stateMapFileName = GetStateMapFileName(stateMapName); + const auto file = searchPath->Open(stateMapFileName); + if (!file.IsOpen()) + return nullptr; + + const state_map::StateMapReader reader(*file.m_stream, stateMapFileName, stateMapName, stateMapLayout); + auto stateMapDefinition = reader.ReadStateMapDefinition(); + if (!stateMapDefinition) + return nullptr; + + const auto* stateMapDefinitionPtr = stateMapDefinition.get(); + + stateMapCache->AddStateMapToCache(std::move(stateMapDefinition)); + + return stateMapDefinitionPtr; +} + bool AssetLoaderTechniqueSet::CanLoadFromRaw() const { return true; diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h index c11d95dc..67d3c7ac 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h @@ -3,6 +3,8 @@ #include "Game/IW4/IW4.h" #include "AssetLoading/BasicAssetLoader.h" #include "SearchPath/ISearchPath.h" +#include "StateMap/StateMapDefinition.h" +#include "Techset/TechniqueStateMapCache.h" #include "Techset/TechsetDefinition.h" #include "Techset/TechsetDefinitionCache.h" @@ -11,11 +13,13 @@ namespace IW4 class AssetLoaderTechniqueSet final : public BasicAssetLoader { static std::string GetTechsetFileName(const std::string& techsetAssetName); + static std::string GetStateMapFileName(const std::string& stateMapName); static bool CreateTechsetFromDefinition(const std::string& assetName, const techset::TechsetDefinition& definition, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); public: static techset::TechsetDefinition* LoadTechsetDefinition(const std::string& assetName, ISearchPath* searchPath, techset::TechsetDefinitionCache* definitionCache); + static const state_map::StateMapDefinition* LoadStateMapDefinition(const std::string& stateMapName, ISearchPath* searchPath, techset::TechniqueStateMapCache* stateMapCache); _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD bool CanLoadFromRaw() const override; diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp b/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp index 8b102131..9e95bc67 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp +++ b/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp @@ -142,8 +142,8 @@ namespace state_map }; } -StateMapParser::StateMapParser(SimpleLexer* lexer, const StateMapLayout& layout) - : AbstractParser(lexer, std::make_unique(layout)) +StateMapParser::StateMapParser(SimpleLexer* lexer, std::string stateMapName, const StateMapLayout& layout) + : AbstractParser(lexer, std::make_unique(std::move(stateMapName), layout)) { } diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParser.h b/src/ObjLoading/StateMap/Parsing/StateMapParser.h index 2f88fc58..9dc49043 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParser.h +++ b/src/ObjLoading/StateMap/Parsing/StateMapParser.h @@ -15,7 +15,7 @@ namespace state_map const std::vector& GetTestsForState() override; public: - StateMapParser(SimpleLexer* lexer, const StateMapLayout& layout); + StateMapParser(SimpleLexer* lexer, std::string stateMapName, const StateMapLayout& layout); _NODISCARD std::unique_ptr GetStateMapDefinition() const; _NODISCARD StateMapParserState* GetState() const; }; diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParserState.cpp b/src/ObjLoading/StateMap/Parsing/StateMapParserState.cpp index b6ad9cf4..aa1b35b4 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParserState.cpp +++ b/src/ObjLoading/StateMap/Parsing/StateMapParserState.cpp @@ -2,11 +2,12 @@ using namespace state_map; -StateMapParserState::StateMapParserState(const StateMapLayout& layout) +StateMapParserState::StateMapParserState(std::string stateMapName, const StateMapLayout& layout) : m_layout(layout), - m_definition(std::make_unique(layout.m_layout_entries.size())), + m_definition(std::make_unique(std::move(stateMapName), layout.m_layout_entries.size())), m_in_entry(false), - m_current_entry_index(0u) + m_current_entry_index(0u), + m_current_rule(nullptr) { for (auto i = 0u; i < m_layout.m_layout_entries.size(); i++) m_valid_state_map_entry_names.emplace(m_layout.m_layout_entries[i].m_name, i); diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParserState.h b/src/ObjLoading/StateMap/Parsing/StateMapParserState.h index 1c0aa50d..5c981eeb 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParserState.h +++ b/src/ObjLoading/StateMap/Parsing/StateMapParserState.h @@ -20,6 +20,6 @@ namespace state_map size_t m_current_entry_index; StateMapRule* m_current_rule; - explicit StateMapParserState(const StateMapLayout& layout); + StateMapParserState(std::string stateMapName, const StateMapLayout& layout); }; } diff --git a/src/ObjLoading/StateMap/StateMapDefinition.cpp b/src/ObjLoading/StateMap/StateMapDefinition.cpp index c5f77376..3f23db1b 100644 --- a/src/ObjLoading/StateMap/StateMapDefinition.cpp +++ b/src/ObjLoading/StateMap/StateMapDefinition.cpp @@ -7,7 +7,8 @@ bool StateMapRule::IsPassthrough() const return m_values.empty(); } -StateMapDefinition::StateMapDefinition(const size_t entryCount) - : m_state_map_entries(entryCount) +StateMapDefinition::StateMapDefinition(std::string name, const size_t entryCount) + : m_name(std::move(name)), + m_state_map_entries(entryCount) { } diff --git a/src/ObjLoading/StateMap/StateMapDefinition.h b/src/ObjLoading/StateMap/StateMapDefinition.h index 2c22ad2b..9b10148f 100644 --- a/src/ObjLoading/StateMap/StateMapDefinition.h +++ b/src/ObjLoading/StateMap/StateMapDefinition.h @@ -1,4 +1,5 @@ #pragma once + #include #include #include @@ -26,8 +27,9 @@ namespace state_map class StateMapDefinition { public: - explicit StateMapDefinition(size_t entryCount); + StateMapDefinition(std::string name, size_t entryCount); + std::string m_name; std::vector m_state_map_entries; }; } diff --git a/src/ObjLoading/StateMap/StateMapReader.cpp b/src/ObjLoading/StateMap/StateMapReader.cpp index e75c38e0..6f913573 100644 --- a/src/ObjLoading/StateMap/StateMapReader.cpp +++ b/src/ObjLoading/StateMap/StateMapReader.cpp @@ -8,8 +8,9 @@ using namespace state_map; -StateMapReader::StateMapReader(std::istream& stream, std::string fileName, const StateMapLayout& layout) - : m_file_name(std::move(fileName)), +StateMapReader::StateMapReader(std::istream& stream, std::string fileName, std::string stateMapName, const StateMapLayout& layout) + : m_state_map_name(std::move(stateMapName)), + m_file_name(std::move(fileName)), m_state_map_layout(layout) { m_base_stream = std::make_unique(stream, m_file_name); @@ -42,7 +43,7 @@ std::unique_ptr StateMapReader::ReadStateMapDefinition() con lexerConfig.m_read_floating_point_numbers = false; const auto lexer = std::make_unique(m_comment_proxy.get(), std::move(lexerConfig)); - const auto parser = std::make_unique(lexer.get(), m_state_map_layout); + const auto parser = std::make_unique(lexer.get(), m_state_map_name, m_state_map_layout); const auto success = parser->Parse(); if (!success) diff --git a/src/ObjLoading/StateMap/StateMapReader.h b/src/ObjLoading/StateMap/StateMapReader.h index 2338097f..bb89aeb3 100644 --- a/src/ObjLoading/StateMap/StateMapReader.h +++ b/src/ObjLoading/StateMap/StateMapReader.h @@ -13,13 +13,14 @@ namespace state_map { class StateMapReader { + std::string m_state_map_name; std::string m_file_name; const StateMapLayout& m_state_map_layout; std::unique_ptr m_base_stream; std::unique_ptr m_comment_proxy; public: - StateMapReader(std::istream& stream, std::string fileName, const StateMapLayout& layout); + StateMapReader(std::istream& stream, std::string fileName, std::string stateMapName, const StateMapLayout& layout); _NODISCARD bool IsValidEndState(const StateMapParserState* state) const; _NODISCARD std::unique_ptr ReadStateMapDefinition() const; diff --git a/src/ObjLoading/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp b/src/ObjLoading/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp index ae60f3db..76631ff5 100644 --- a/src/ObjLoading/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp +++ b/src/ObjLoading/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp @@ -29,7 +29,7 @@ namespace techset assert(state->m_in_pass == true); std::string errorMessage; - if(!state->m_acceptor->AcceptEndPass(errorMessage)) + if (!state->m_acceptor->AcceptEndPass(errorMessage)) throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), errorMessage); state->m_in_pass = false; @@ -38,7 +38,8 @@ namespace techset class SequenceStateMap final : public TechniqueParser::sequence_t { - static constexpr auto CAPTURE_STATE_MAP_NAME = 1; + static constexpr auto CAPTURE_START = 1; + static constexpr auto CAPTURE_STATE_MAP_NAME = 2; public: SequenceStateMap() @@ -46,7 +47,7 @@ namespace techset const SimpleMatcherFactory create(this); AddMatchers({ - create.Keyword("stateMap"), + create.Keyword("stateMap").Capture(CAPTURE_START), create.String().Capture(CAPTURE_STATE_MAP_NAME), create.Char(';') }); @@ -55,7 +56,13 @@ namespace techset protected: void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { - state->m_acceptor->AcceptStateMap(result.NextCapture(CAPTURE_STATE_MAP_NAME).StringValue()); + const auto& firstToken = result.NextCapture(CAPTURE_START); + + std::string errorMessage; + const auto acceptorResult = state->m_acceptor->AcceptStateMap(result.NextCapture(CAPTURE_STATE_MAP_NAME).StringValue(), errorMessage); + + if (!acceptorResult) + throw ParsingException(firstToken.GetPos(), std::move(errorMessage)); } }; diff --git a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h index 160a28d7..2b1975a5 100644 --- a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h +++ b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h @@ -76,7 +76,7 @@ namespace techset virtual void AcceptNextPass() = 0; virtual bool AcceptEndPass(std::string& errorMessage) = 0; - virtual void AcceptStateMap(const std::string& stateMapName) = 0; + virtual bool AcceptStateMap(const std::string& stateMapName, std::string& errorMessage) = 0; virtual bool AcceptVertexShader(const std::string& vertexShaderName, std::string& errorMessage) = 0; virtual bool AcceptPixelShader(const std::string& pixelShaderName, std::string& errorMessage) = 0; diff --git a/src/ObjLoading/Techset/TechniqueStateMapCache.cpp b/src/ObjLoading/Techset/TechniqueStateMapCache.cpp index 5dae972a..f97713a6 100644 --- a/src/ObjLoading/Techset/TechniqueStateMapCache.cpp +++ b/src/ObjLoading/Techset/TechniqueStateMapCache.cpp @@ -1,3 +1,33 @@ #include "TechniqueStateMapCache.h" using namespace techset; + +const state_map::StateMapDefinition* TechniqueStateMapCache::GetCachedStateMap(const std::string& name) const +{ + const auto foundStateMap = m_state_map_cache.find(name); + + if (foundStateMap != m_state_map_cache.end()) + return foundStateMap->second.get(); + + return nullptr; +} + +void TechniqueStateMapCache::AddStateMapToCache(std::unique_ptr stateMap) +{ + m_state_map_cache.emplace(std::make_pair(stateMap->m_name, std::move(stateMap))); +} + +const state_map::StateMapDefinition* TechniqueStateMapCache::GetStateMapForTechnique(const std::string& techniqueName) const +{ + const auto foundTechnique = m_state_map_per_technique.find(techniqueName); + + if (foundTechnique != m_state_map_per_technique.end()) + return foundTechnique->second; + + return nullptr; +} + +void TechniqueStateMapCache::SetTechniqueUsesStateMap(std::string techniqueName, const state_map::StateMapDefinition* stateMap) +{ + m_state_map_per_technique.emplace(std::make_pair(std::move(techniqueName), stateMap)); +} diff --git a/src/ObjLoading/Techset/TechniqueStateMapCache.h b/src/ObjLoading/Techset/TechniqueStateMapCache.h index 99ff275e..2b0eea23 100644 --- a/src/ObjLoading/Techset/TechniqueStateMapCache.h +++ b/src/ObjLoading/Techset/TechniqueStateMapCache.h @@ -1,10 +1,26 @@ #pragma once +#include +#include +#include + +#include "AssetLoading/IZoneAssetLoaderState.h" +#include "Utils/ClassUtils.h" +#include "StateMap/StateMapDefinition.h" + namespace techset { - class TechniqueStateMapCache + class TechniqueStateMapCache final : public IZoneAssetLoaderState { - // TODO: Cache which state map is being used for which technique - // TODO: Cache state map data + public: + _NODISCARD const state_map::StateMapDefinition* GetCachedStateMap(const std::string& name) const; + void AddStateMapToCache(std::unique_ptr stateMap); + + _NODISCARD const state_map::StateMapDefinition* GetStateMapForTechnique(const std::string& techniqueName) const; + void SetTechniqueUsesStateMap(std::string techniqueName, const state_map::StateMapDefinition* stateMap); + + private: + std::unordered_map m_state_map_per_technique; + std::unordered_map> m_state_map_cache; }; }