diff --git a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h index 599f6de7..bd36ace6 100644 --- a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h +++ b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h @@ -580,7 +580,7 @@ namespace IW4 inline state_map::StateMapLayoutEntries stateMapEntryLayout({ { - "alphaTest", 0, GFXS0_ATEST_MASK, { + "alphaTest", 0, GFXS0_ATEST_MASK | GFXS0_ATEST_DISABLE, { "mtlAlphaTest" } }, @@ -604,7 +604,7 @@ namespace IW4 } }, { - "depthTest", 1, GFXS1_DEPTHTEST_MASK, { + "depthTest", 1, GFXS1_DEPTHTEST_MASK | GFXS1_DEPTHTEST_DISABLE, { "mtlDepthTest" } }, diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp index 803cd319..bff97b93 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp @@ -12,8 +12,12 @@ #include "Game/IW4/IW4.h" #include "Game/IW4/MaterialConstantsIW4.h" #include "Game/IW4/ObjConstantsIW4.h" +#include "Game/IW4/TechsetConstantsIW4.h" #include "Math/Vector.h" #include "Pool/GlobalAssetPool.h" +#include "StateMap/StateMapFromTechniqueExtractor.h" +#include "StateMap/StateMapHandler.h" +#include "Techset/TechniqueFileReader.h" using namespace IW4; @@ -26,10 +30,12 @@ namespace IW4 class MaterialGdtLoader : AbstractGdtEntryReader { public: - MaterialGdtLoader(const GdtEntry& entry, MemoryManager* memory, IAssetLoadingManager* manager) + MaterialGdtLoader(const GdtEntry& entry, MemoryManager* memory, ISearchPath* searchPath, IAssetLoadingManager* manager) : AbstractGdtEntryReader(entry), m_memory(memory), + m_search_path(searchPath), m_manager(manager), + m_state_map_cache(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()), m_material(nullptr), m_base_state_bits{} { @@ -167,6 +173,9 @@ namespace IW4 void mtl_effect_template() { + // TODO + throw SkipMaterialException(); + commonsetup_template(); unitlitcommon_template(); } @@ -847,6 +856,58 @@ namespace IW4 } } + GfxStateBits GetStateBitsForTechnique(const std::string& techniqueName) + { + const auto* stateMap = GetStateMapForTechnique(techniqueName); + if (!stateMap) + return m_base_state_bits; + + const auto preCalculatedStateBits = m_state_bits_per_state_map.find(stateMap); + if (preCalculatedStateBits != m_state_bits_per_state_map.end()) + return preCalculatedStateBits->second; + + const auto stateBits = CalculateStateBitsWithStateMap(stateMap); + m_state_bits_per_state_map.emplace(stateMap, stateBits); + + return stateBits; + } + + _NODISCARD const state_map::StateMapDefinition* GetStateMapForTechnique(const std::string& techniqueName) const + { + const auto* preloadedStateMap = m_state_map_cache->GetStateMapForTechnique(techniqueName); + if (preloadedStateMap) + return preloadedStateMap; + + const auto techniqueFileName = AssetLoaderTechniqueSet::GetTechniqueFileName(techniqueName); + const auto file = m_search_path->Open(techniqueFileName); + if (!file.IsOpen()) + return nullptr; + + state_map::StateMapFromTechniqueExtractor extractor; + const techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &extractor); + if (!reader.ReadTechniqueDefinition()) + { + m_state_map_cache->SetTechniqueUsesStateMap(techniqueName, nullptr); + return nullptr; + } + + const auto stateMapName = extractor.RetrieveStateMap(); + const auto* loadedStateMap = AssetLoaderTechniqueSet::LoadStateMapDefinition(stateMapName, m_search_path, m_state_map_cache); + m_state_map_cache->SetTechniqueUsesStateMap(techniqueName, loadedStateMap); + + return loadedStateMap; + } + + GfxStateBits CalculateStateBitsWithStateMap(const state_map::StateMapDefinition* stateMap) const + { + const state_map::StateMapHandler stateMapHandler(stateMapLayout, *stateMap); + + GfxStateBits outBits{}; + stateMapHandler.ApplyStateMap(m_base_state_bits.loadBits, outBits.loadBits); + + return outBits; + } + void SetTechniqueSetCameraRegion(const techset::TechsetDefinition* techsetDefinition) const { std::string tempName; @@ -867,12 +928,6 @@ namespace IW4 } } - GfxStateBits GetStateBitsForTechnique(const std::string& techniqueName) - { - // TODO: Use technique statemap to evaluate actual statebits - return m_base_state_bits; - } - void AddMapTexture(const std::string& typeName, const TileMode_e tileMode, GdtFilter_e filterMode, const TextureSemantic semantic, const std::string& textureName) { MaterialTextureDef textureDef{}; @@ -1263,7 +1318,10 @@ namespace IW4 } MemoryManager* m_memory; + ISearchPath* m_search_path; IAssetLoadingManager* m_manager; + techset::TechniqueStateMapCache* m_state_map_cache; + std::unordered_map m_state_bits_per_state_map; std::vector m_dependencies; Material* m_material; @@ -1293,7 +1351,7 @@ bool AssetLoaderMaterial::LoadFromGdt(const std::string& assetName, IGdtQueryabl if (!entry) return false; - MaterialGdtLoader loader(*entry, memory, manager); + MaterialGdtLoader loader(*entry, memory, manager->GetAssetLoadingContext()->m_raw_search_path, manager); try { diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp index d09192f9..74cb7384 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp @@ -1007,13 +1007,6 @@ namespace IW4 ShaderInfoFromFileSystemCacheState* m_shader_info_cache; techset::TechniqueStateMapCache* m_state_map_cache; - static std::string GetTechniqueFileName(const std::string& techniqueName) - { - std::ostringstream ss; - ss << "techniques/" << techniqueName << ".tech"; - return ss.str(); - } - static void UpdateTechniqueFlags(MaterialTechnique& technique) { // This is stupid but that's what the game does for zprepass for sure @@ -1200,7 +1193,7 @@ namespace IW4 MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, std::vector& dependencies) const { - const auto techniqueFileName = GetTechniqueFileName(techniqueName); + const auto techniqueFileName = AssetLoaderTechniqueSet::GetTechniqueFileName(techniqueName); const auto file = m_search_path->Open(techniqueFileName); if (!file.IsOpen()) return nullptr; @@ -1255,6 +1248,13 @@ std::string AssetLoaderTechniqueSet::GetTechsetFileName(const std::string& techs return ss.str(); } +std::string AssetLoaderTechniqueSet::GetTechniqueFileName(const std::string& techniqueName) +{ + std::ostringstream ss; + ss << "techniques/" << techniqueName << ".tech"; + return ss.str(); +} + std::string AssetLoaderTechniqueSet::GetStateMapFileName(const std::string& stateMapName) { std::ostringstream ss; diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h index 67d3c7ac..fe33e504 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h @@ -12,12 +12,14 @@ 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 std::string GetTechsetFileName(const std::string& techsetAssetName); + static std::string GetTechniqueFileName(const std::string& techniqueName); + static std::string GetStateMapFileName(const std::string& stateMapName); + 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); diff --git a/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.cpp b/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.cpp index 3b235a2b..79a269d7 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.cpp +++ b/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.cpp @@ -42,7 +42,7 @@ SimpleExpressionValue CommonExpressionBaseFunctionCall::EvaluateStatic() const return SimpleExpressionValue(0); } -SimpleExpressionValue CommonExpressionBaseFunctionCall::EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const +SimpleExpressionValue CommonExpressionBaseFunctionCall::EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const { return SimpleExpressionValue(0); } diff --git a/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.h b/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.h index d5a4e356..f558e02e 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.h +++ b/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.h @@ -17,6 +17,6 @@ namespace menu _NODISCARD bool Equals(const ISimpleExpression* other) const override; _NODISCARD bool IsStatic() const override; _NODISCARD SimpleExpressionValue EvaluateStatic() const override; - _NODISCARD SimpleExpressionValue EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const override; + _NODISCARD SimpleExpressionValue EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const override; }; } diff --git a/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.cpp b/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.cpp index 43007218..ae53ee2b 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.cpp +++ b/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.cpp @@ -23,7 +23,7 @@ SimpleExpressionValue CommonExpressionCustomFunctionCall::EvaluateStatic() const return SimpleExpressionValue(0); } -SimpleExpressionValue CommonExpressionCustomFunctionCall::EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const +SimpleExpressionValue CommonExpressionCustomFunctionCall::EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const { return SimpleExpressionValue(0); } diff --git a/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.h b/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.h index 98cabc23..f226c098 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.h +++ b/src/ObjLoading/Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.h @@ -14,6 +14,6 @@ namespace menu _NODISCARD bool Equals(const ISimpleExpression* other) const override; _NODISCARD bool IsStatic() const override; _NODISCARD SimpleExpressionValue EvaluateStatic() const override; - _NODISCARD SimpleExpressionValue EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const override; + _NODISCARD SimpleExpressionValue EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const override; }; } diff --git a/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.cpp b/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.cpp index 3e38a65a..70a9b81c 100644 --- a/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.cpp +++ b/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.cpp @@ -5,10 +5,16 @@ using namespace state_map; -static constexpr int CAPTURE_IDENTIFIER = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION_EXT + 1; +static constexpr int CAPTURE_VALUE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION_EXT + 1; StateMapExpressionMatchers::StateMapExpressionMatchers() - : SimpleExpressionMatchers(false, false, false, false, true) + : StateMapExpressionMatchers(nullptr) +{ +} + +StateMapExpressionMatchers::StateMapExpressionMatchers(StateMapParserState* state) + : SimpleExpressionMatchers(false, false, false, false, true), + m_state(state) { } @@ -17,17 +23,28 @@ std::unique_ptr StateMapExpressionMatchers: const SimpleMatcherFactory create(labelSupplier); return create.Or({ - create.Identifier().Capture(CAPTURE_IDENTIFIER) + create.Identifier().Capture(CAPTURE_VALUE), + create.Integer().Capture(CAPTURE_VALUE), }); } std::unique_ptr StateMapExpressionMatchers::ProcessOperandExtension(SequenceResult& result) const { - const auto& identifierToken = result.NextCapture(CAPTURE_IDENTIFIER); - auto identifierValue = identifierToken.IdentifierValue(); + assert(m_state); - if (identifierValue.rfind("mtl", 0) == 0) - return std::make_unique(identifierValue); + const auto& valueToken = result.NextCapture(CAPTURE_VALUE); + auto value = valueToken.m_type == SimpleParserValueType::IDENTIFIER ? valueToken.IdentifierValue() : std::to_string(valueToken.IntegerValue()); - return std::make_unique(identifierValue); + if (value.rfind("mtl", 0) == 0) + { + if (m_state->m_valid_vars.find(value) == m_state->m_valid_vars.end()) + throw ParsingException(valueToken.GetPos(), "Unknown variable"); + + return std::make_unique(value); + } + + if (m_state->m_valid_values.find(value) == m_state->m_valid_values.end()) + throw ParsingException(valueToken.GetPos(), "Unknown value"); + + return std::make_unique(value); } diff --git a/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.h b/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.h index b2d5215e..5be3ea1e 100644 --- a/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.h +++ b/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.h @@ -3,6 +3,7 @@ #include #include "Parsing/Simple/Expression/SimpleExpressionMatchers.h" +#include "StateMap/Parsing/StateMapParserState.h" namespace state_map { @@ -10,9 +11,13 @@ namespace state_map { public: StateMapExpressionMatchers(); + explicit StateMapExpressionMatchers(StateMapParserState* state); protected: std::unique_ptr ParseOperandExtension(const supplier_t* labelSupplier) const override; std::unique_ptr ProcessOperandExtension(SequenceResult& result) const override; + + private: + StateMapParserState* m_state; }; } diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp b/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp index ad890a56..406bfa97 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp +++ b/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp @@ -38,20 +38,26 @@ namespace state_map class SequenceStateMapEntryClose final : public StateMapParser::sequence_t { + static constexpr auto CAPTURE_FIRST_TOKEN = 1; + public: SequenceStateMapEntryClose() { const SimpleMatcherFactory create(this); AddMatchers({ - create.Char('}') + create.Char('}').Capture(CAPTURE_FIRST_TOKEN) }); } protected: void ProcessMatch(StateMapParserState* state, SequenceResult& result) const override { + if (!state->m_entry_has_default) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Entry must have a default case"); + state->m_in_entry = false; + state->m_entry_has_default = false; } }; @@ -63,7 +69,7 @@ namespace state_map public: SequenceCondition() { - AddLabeledMatchers(m_expression_matchers.Expression(this), StateMapExpressionMatchers::LABEL_EXPRESSION); + AddLabeledMatchers(StateMapExpressionMatchers().Expression(this), StateMapExpressionMatchers::LABEL_EXPRESSION); const SimpleMatcherFactory create(this); AddMatchers({ @@ -90,7 +96,7 @@ namespace state_map if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) == TAG_EXPRESSION) { - auto expression = m_expression_matchers.ProcessExpression(result); + auto expression = StateMapExpressionMatchers(state).ProcessExpression(result); state->m_current_rule->m_conditions.emplace_back(std::move(expression)); } @@ -98,13 +104,10 @@ namespace state_map { assert(result.PeekAndRemoveIfTag(TAG_DEFAULT) == TAG_DEFAULT); auto& entry = state->m_definition->m_state_map_entries[state->m_current_entry_index]; - entry.m_has_default = true; + state->m_entry_has_default = true; entry.m_default_index = entry.m_rules.size() - 1; } } - - private: - StateMapExpressionMatchers m_expression_matchers; }; class SequenceValue final : public StateMapParser::sequence_t @@ -113,19 +116,26 @@ namespace state_map static constexpr auto TAG_VALUE_LIST = 2; static constexpr auto CAPTURE_VALUE = 1; + static constexpr auto CAPTURE_VALUE_END = 2; static constexpr auto LABEL_VALUE_LIST = 1; + static constexpr auto LABEL_VALUE = 2; public: SequenceValue() { const SimpleMatcherFactory create(this); + AddLabeledMatchers(create.Or({ + create.Identifier(), + create.Integer() + }), LABEL_VALUE); + AddLabeledMatchers({ - create.Identifier().Capture(CAPTURE_VALUE), + create.Label(LABEL_VALUE).Capture(CAPTURE_VALUE), create.OptionalLoop(create.And({ create.Char(','), - create.Identifier().Capture(CAPTURE_VALUE) + create.Label(LABEL_VALUE).Capture(CAPTURE_VALUE) })) }, LABEL_VALUE_LIST); @@ -134,7 +144,7 @@ namespace state_map create.Keyword("passthrough").Tag(TAG_PASSTHROUGH), create.Label(LABEL_VALUE_LIST).Tag(TAG_VALUE_LIST) }), - create.Char(';') + create.Char(';').Capture(CAPTURE_VALUE_END) }); } @@ -144,15 +154,51 @@ namespace state_map assert(state->m_in_entry); assert(state->m_current_rule); + const auto& layoutEntry = state->m_layout.m_entry_layout.m_entries[state->m_current_entry_index]; + if (result.PeekAndRemoveIfTag(TAG_VALUE_LIST) == TAG_VALUE_LIST) { + auto resultIndex = 0u; + while (result.HasNextCapture(CAPTURE_VALUE)) - state->m_current_rule->m_values.emplace_back(result.NextCapture(CAPTURE_VALUE).IdentifierValue()); + { + const auto& valueToken = result.NextCapture(CAPTURE_VALUE); + + if (resultIndex >= layoutEntry.m_result_vars.size()) + throw ParsingException(valueToken.GetPos(), "Too many results"); + + const auto& resultVar = layoutEntry.m_result_vars[resultIndex]; + const auto varForResult = state->m_valid_vars.find(resultVar); + + if (varForResult != state->m_valid_vars.end()) + { + const auto& var = state->m_layout.m_var_layout.m_vars[varForResult->second]; + const auto tokenValue = valueToken.m_type == SimpleParserValueType::IDENTIFIER ? valueToken.IdentifierValue() : std::to_string(valueToken.IntegerValue()); + + const auto referencedValue = std::find_if(var.m_values.begin(), var.m_values.end(), [&tokenValue](const StateMapLayoutVarValue& value) + { + return value.m_name == tokenValue; + }); + + if (referencedValue == var.m_values.end()) + throw ParsingException(valueToken.GetPos(), "Not part of the valid values for this var"); + + state->m_current_rule->m_value |= referencedValue->m_state_bits_mask; + } + else + throw ParsingException(valueToken.GetPos(), "Unknown var for result?"); + + resultIndex++; + } + + if (resultIndex < layoutEntry.m_result_vars.size()) + throw ParsingException(result.NextCapture(CAPTURE_VALUE_END).GetPos(), "Not enough results"); } else { // A rule without values is considered passthrough therefore just don't add values assert(result.PeekAndRemoveIfTag(TAG_PASSTHROUGH) == TAG_PASSTHROUGH); + state->m_current_rule->m_passthrough = true; } state->m_current_rule = nullptr; diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParserState.cpp b/src/ObjLoading/StateMap/Parsing/StateMapParserState.cpp index 91b7808a..cea85887 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParserState.cpp +++ b/src/ObjLoading/StateMap/Parsing/StateMapParserState.cpp @@ -6,9 +6,19 @@ StateMapParserState::StateMapParserState(std::string stateMapName, const StateMa : m_layout(layout), m_definition(std::make_unique(std::move(stateMapName), layout.m_entry_layout.m_entries.size())), m_in_entry(false), + m_entry_has_default(false), m_current_entry_index(0u), m_current_rule(nullptr) { for (auto i = 0u; i < m_layout.m_entry_layout.m_entries.size(); i++) m_valid_state_map_entry_names.emplace(m_layout.m_entry_layout.m_entries[i].m_name, i); + + for (auto varIndex = 0u; varIndex < layout.m_var_layout.m_vars.size(); varIndex++) + { + const auto& var = layout.m_var_layout.m_vars[varIndex]; + m_valid_vars.emplace(std::make_pair(var.m_name, varIndex)); + + for (const auto& value : var.m_values) + m_valid_values.emplace(value.m_name); + } } diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParserState.h b/src/ObjLoading/StateMap/Parsing/StateMapParserState.h index 5c981eeb..6a056fb5 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParserState.h +++ b/src/ObjLoading/StateMap/Parsing/StateMapParserState.h @@ -1,7 +1,8 @@ #pragma once -#include +#include #include +#include #include #include "StateMap/StateMapDefinition.h" @@ -13,10 +14,13 @@ namespace state_map { public: const StateMapLayout& m_layout; - std::map m_valid_state_map_entry_names; + std::unordered_map m_valid_state_map_entry_names; + std::unordered_map m_valid_vars; + std::set m_valid_values; std::unique_ptr m_definition; bool m_in_entry; + bool m_entry_has_default; size_t m_current_entry_index; StateMapRule* m_current_rule; diff --git a/src/ObjLoading/StateMap/StateMapDefinition.cpp b/src/ObjLoading/StateMap/StateMapDefinition.cpp index e8b64045..e2cfc092 100644 --- a/src/ObjLoading/StateMap/StateMapDefinition.cpp +++ b/src/ObjLoading/StateMap/StateMapDefinition.cpp @@ -2,14 +2,14 @@ using namespace state_map; -bool StateMapRule::IsPassthrough() const +StateMapRule::StateMapRule() + : m_value(0u), + m_passthrough(false) { - return m_values.empty(); } StateMapEntry::StateMapEntry() - : m_has_default(false), - m_default_index(0u) + : m_default_index(0u) { } diff --git a/src/ObjLoading/StateMap/StateMapDefinition.h b/src/ObjLoading/StateMap/StateMapDefinition.h index 173ef994..4b691cbd 100644 --- a/src/ObjLoading/StateMap/StateMapDefinition.h +++ b/src/ObjLoading/StateMap/StateMapDefinition.h @@ -4,7 +4,6 @@ #include #include -#include "Utils/ClassUtils.h" #include "Parsing/Simple/Expression/ISimpleExpression.h" namespace state_map @@ -13,15 +12,15 @@ namespace state_map { public: std::vector> m_conditions; - std::vector m_values; - - _NODISCARD bool IsPassthrough() const; + size_t m_value; + bool m_passthrough; + + StateMapRule(); }; class StateMapEntry { public: - bool m_has_default; size_t m_default_index; std::vector> m_rules; diff --git a/src/ObjLoading/StateMap/StateMapFromTechniqueExtractor.cpp b/src/ObjLoading/StateMap/StateMapFromTechniqueExtractor.cpp new file mode 100644 index 00000000..182e5014 --- /dev/null +++ b/src/ObjLoading/StateMap/StateMapFromTechniqueExtractor.cpp @@ -0,0 +1,58 @@ +#include "StateMapFromTechniqueExtractor.h" + +using namespace state_map; + +std::string StateMapFromTechniqueExtractor::RetrieveStateMap() +{ + return std::move(m_state_map); +} + +void StateMapFromTechniqueExtractor::AcceptNextPass() +{ +} + +bool StateMapFromTechniqueExtractor::AcceptEndPass(std::string& errorMessage) +{ + return true; +} + +bool StateMapFromTechniqueExtractor::AcceptStateMap(const std::string& stateMapName, std::string& errorMessage) +{ + m_state_map = stateMapName; + return true; +} + +bool StateMapFromTechniqueExtractor::AcceptVertexShader(const std::string& vertexShaderName, std::string& errorMessage) +{ + return true; +} + +bool StateMapFromTechniqueExtractor::AcceptPixelShader(const std::string& pixelShaderName, std::string& errorMessage) +{ + return true; +} + +bool StateMapFromTechniqueExtractor::AcceptShaderConstantArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentCodeSource source, std::string& errorMessage) +{ + return true; +} + +bool StateMapFromTechniqueExtractor::AcceptShaderSamplerArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentCodeSource source, std::string& errorMessage) +{ + return true; +} + +bool StateMapFromTechniqueExtractor::AcceptShaderLiteralArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentLiteralSource source, std::string& errorMessage) +{ + return true; +} + +bool StateMapFromTechniqueExtractor::AcceptShaderMaterialArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentMaterialSource source, std::string& errorMessage) +{ + return true; +} + +bool StateMapFromTechniqueExtractor::AcceptVertexStreamRouting(const std::string& destination, const std::string& source, std::string& errorMessage) +{ + return true; +} diff --git a/src/ObjLoading/StateMap/StateMapFromTechniqueExtractor.h b/src/ObjLoading/StateMap/StateMapFromTechniqueExtractor.h new file mode 100644 index 00000000..217d7ea6 --- /dev/null +++ b/src/ObjLoading/StateMap/StateMapFromTechniqueExtractor.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "Techset/TechniqueDefinitionAcceptor.h" + +namespace state_map +{ + class StateMapFromTechniqueExtractor final : public techset::ITechniqueDefinitionAcceptor + { + public: + std::string RetrieveStateMap(); + + void AcceptNextPass() override; + bool AcceptEndPass(std::string& errorMessage) override; + bool AcceptStateMap(const std::string& stateMapName, std::string& errorMessage) override; + bool AcceptVertexShader(const std::string& vertexShaderName, std::string& errorMessage) override; + bool AcceptPixelShader(const std::string& pixelShaderName, std::string& errorMessage) override; + bool AcceptShaderConstantArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentCodeSource source, std::string& errorMessage) override; + bool AcceptShaderSamplerArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentCodeSource source, std::string& errorMessage) override; + bool AcceptShaderLiteralArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentLiteralSource source, std::string& errorMessage) override; + bool AcceptShaderMaterialArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentMaterialSource source, std::string& errorMessage) override; + bool AcceptVertexStreamRouting(const std::string& destination, const std::string& source, std::string& errorMessage) override; + + private: + std::string m_state_map; + }; +} diff --git a/src/ObjLoading/StateMap/StateMapHandler.cpp b/src/ObjLoading/StateMap/StateMapHandler.cpp new file mode 100644 index 00000000..aa2bc88b --- /dev/null +++ b/src/ObjLoading/StateMap/StateMapHandler.cpp @@ -0,0 +1,87 @@ +#include "StateMapHandler.h" + +#include +#include + +using namespace state_map; + +void StateMapVars::AddValue(std::string key, std::string value) +{ + m_vars.emplace(std::make_pair(std::move(key), std::move(value))); +} + +SimpleExpressionValue StateMapVars::ValueByName(const std::string& name) const +{ + const auto foundValue = m_vars.find(name); + + if (foundValue != m_vars.end()) + return SimpleExpressionValue(foundValue->second); + + return SimpleExpressionValue(0); +} + +StateMapHandler::StateMapHandler(const StateMapLayout& stateMapLayout, const StateMapDefinition& stateMap) + : m_state_map_layout(stateMapLayout), + m_state_map(stateMap) +{ +} + +void StateMapHandler::ApplyStateMap(const uint32_t* baseStateBits, uint32_t* outStateBits) const +{ + assert(baseStateBits != nullptr); + assert(outStateBits != nullptr); + + const auto vars = BuildVars(baseStateBits); + + for (auto i = 0u; i < m_state_map_layout.m_state_bits_count; i++) + outStateBits[i] = baseStateBits[i]; + + for (auto entryIndex = 0u; entryIndex < m_state_map.m_state_map_entries.size(); entryIndex++) + { + const auto& entry = m_state_map.m_state_map_entries[entryIndex]; + const auto matchingRule = std::find_if(entry.m_rules.begin(), entry.m_rules.end(), [&vars](const std::unique_ptr& rule) + { + const auto matchingCondition = std::find_if(rule->m_conditions.begin(), rule->m_conditions.end(), [&vars](std::unique_ptr& condition) + { + return condition->EvaluateNonStatic(&vars).IsTruthy(); + }); + + return matchingCondition != rule->m_conditions.end(); + }); + + if (matchingRule != entry.m_rules.end()) + ApplyRule(m_state_map_layout.m_entry_layout.m_entries[entryIndex], **matchingRule, outStateBits); + else + ApplyRule(m_state_map_layout.m_entry_layout.m_entries[entryIndex], *entry.m_rules[entry.m_default_index], outStateBits); + } +} + +StateMapVars StateMapHandler::BuildVars(const uint32_t* baseStateBits) const +{ + StateMapVars result; + + for (const auto& var : m_state_map_layout.m_var_layout.m_vars) + { + const auto baseStateBitField = baseStateBits[var.m_state_bits_index]; + const auto matchingValue = std::find_if(var.m_values.begin(), var.m_values.end(), [&baseStateBitField](const StateMapLayoutVarValue& value) + { + return (baseStateBitField & value.m_state_bits_mask) == value.m_state_bits_mask; + }); + + if (matchingValue != var.m_values.end()) + result.AddValue(var.m_name, matchingValue->m_name); + else + std::cerr << "Could not find base value for state map var \"" << var.m_name << "\"\n"; + } + + return result; +} + +void StateMapHandler::ApplyRule(const StateMapLayoutEntry& entry, const StateMapRule& rule, uint32_t* outStateBits) +{ + if (rule.m_passthrough) + return; + + outStateBits[entry.m_state_bits_index] &= ~entry.m_state_bits_mask; + outStateBits[entry.m_state_bits_index] |= rule.m_value; +} diff --git a/src/ObjLoading/StateMap/StateMapHandler.h b/src/ObjLoading/StateMap/StateMapHandler.h new file mode 100644 index 00000000..7fe44933 --- /dev/null +++ b/src/ObjLoading/StateMap/StateMapHandler.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "Utils/ClassUtils.h" +#include "StateMap/StateMapDefinition.h" +#include "StateMap/StateMapLayout.h" + +namespace state_map +{ + class StateMapVars final : public ISimpleExpressionScopeValues + { + public: + void AddValue(std::string key, std::string value); + _NODISCARD SimpleExpressionValue ValueByName(const std::string& name) const override; + + private: + std::unordered_map m_vars; + }; + + class StateMapHandler + { + public: + StateMapHandler(const StateMapLayout& stateMapLayout, const StateMapDefinition& stateMap); + + void ApplyStateMap(const uint32_t* baseStateBits, uint32_t* outStateBits) const; + + private: + StateMapVars BuildVars(const uint32_t* baseStateBits) const; + static void ApplyRule(const StateMapLayoutEntry& entry, const StateMapRule& rule, uint32_t* outStateBits); + + const StateMapLayout& m_state_map_layout; + const StateMapDefinition& m_state_map; + }; +} diff --git a/src/ObjLoading/StateMap/StateMapReader.cpp b/src/ObjLoading/StateMap/StateMapReader.cpp index dfe64ec6..5190350d 100644 --- a/src/ObjLoading/StateMap/StateMapReader.cpp +++ b/src/ObjLoading/StateMap/StateMapReader.cpp @@ -5,6 +5,7 @@ #include "Parsing/StateMapParser.h" #include "Parsing/Impl/CommentRemovingStreamProxy.h" #include "Parsing/Impl/ParserSingleInputStream.h" +#include "Parsing/Matcher/StateMapExpressionMatchers.h" using namespace state_map; @@ -50,6 +51,7 @@ std::unique_ptr StateMapReader::ReadStateMapDefinition() con lexerConfig.m_read_strings = false; lexerConfig.m_read_integer_numbers = true; lexerConfig.m_read_floating_point_numbers = false; + StateMapExpressionMatchers().ApplyTokensToLexerConfig(lexerConfig); const auto lexer = std::make_unique(m_comment_proxy.get(), std::move(lexerConfig)); const auto parser = std::make_unique(lexer.get(), m_state_map_name, m_state_map_layout); diff --git a/src/Parser/Parsing/Simple/Expression/ISimpleExpression.h b/src/Parser/Parsing/Simple/Expression/ISimpleExpression.h index 18342614..97c026b0 100644 --- a/src/Parser/Parsing/Simple/Expression/ISimpleExpression.h +++ b/src/Parser/Parsing/Simple/Expression/ISimpleExpression.h @@ -33,7 +33,7 @@ public: _NODISCARD virtual bool Equals(const ISimpleExpression* other) const = 0; _NODISCARD virtual bool IsStatic() const = 0; _NODISCARD virtual SimpleExpressionValue EvaluateStatic() const = 0; - _NODISCARD virtual SimpleExpressionValue EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const = 0; + _NODISCARD virtual SimpleExpressionValue EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const = 0; }; // Include SimpleExpressionValue after definition to avoid "base class not defined" diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.cpp index 42e44b87..8b4131b7 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.cpp +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.cpp @@ -465,7 +465,7 @@ SimpleExpressionValue SimpleExpressionBinaryOperation::EvaluateStatic() const return m_operation_type->m_evaluation_function(m_operand1->EvaluateStatic(), m_operand2->EvaluateStatic()); } -SimpleExpressionValue SimpleExpressionBinaryOperation::EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const +SimpleExpressionValue SimpleExpressionBinaryOperation::EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const { return m_operation_type->m_evaluation_function(m_operand1->EvaluateNonStatic(scopeValues), m_operand2->EvaluateNonStatic(scopeValues)); } diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h index 5d276ccd..210c1cb9 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h @@ -96,5 +96,5 @@ public: _NODISCARD bool Equals(const ISimpleExpression* other) const override; _NODISCARD bool IsStatic() const override; _NODISCARD SimpleExpressionValue EvaluateStatic() const override; - _NODISCARD SimpleExpressionValue EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const override; + _NODISCARD SimpleExpressionValue EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const override; }; diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.cpp index 40763be3..b945b8b4 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.cpp +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.cpp @@ -31,7 +31,7 @@ SimpleExpressionValue SimpleExpressionConditionalOperator::EvaluateStatic() cons return m_condition->EvaluateStatic().IsTruthy() ? m_true_value->EvaluateStatic() : m_false_value->EvaluateStatic(); } -SimpleExpressionValue SimpleExpressionConditionalOperator::EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const +SimpleExpressionValue SimpleExpressionConditionalOperator::EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const { return m_condition->EvaluateNonStatic(scopeValues).IsTruthy() ? m_true_value->EvaluateNonStatic(scopeValues) diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h index bdbf47ba..3a43483e 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h @@ -11,7 +11,7 @@ public: _NODISCARD bool Equals(const ISimpleExpression* other) const override; _NODISCARD bool IsStatic() const override; _NODISCARD SimpleExpressionValue EvaluateStatic() const override; - _NODISCARD SimpleExpressionValue EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const override; + _NODISCARD SimpleExpressionValue EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const override; SimpleExpressionConditionalOperator(); SimpleExpressionConditionalOperator(std::unique_ptr condition, std::unique_ptr trueExpression, std::unique_ptr falseExpression); diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionScopeValue.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionScopeValue.cpp index 26682e95..215ea4e9 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionScopeValue.cpp +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionScopeValue.cpp @@ -22,7 +22,7 @@ SimpleExpressionValue SimpleExpressionScopeValue::EvaluateStatic() const return SimpleExpressionValue(0); } -SimpleExpressionValue SimpleExpressionScopeValue::EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const +SimpleExpressionValue SimpleExpressionScopeValue::EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const { return scopeValues->ValueByName(m_value_name); } diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionScopeValue.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionScopeValue.h index b6f73976..2d4c78d3 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionScopeValue.h +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionScopeValue.h @@ -15,5 +15,5 @@ public: _NODISCARD bool Equals(const ISimpleExpression* other) const override; _NODISCARD bool IsStatic() const override; _NODISCARD SimpleExpressionValue EvaluateStatic() const override; - _NODISCARD SimpleExpressionValue EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const override; + _NODISCARD SimpleExpressionValue EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const override; }; diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.cpp index 74d5c528..4f908171 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.cpp +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.cpp @@ -83,7 +83,7 @@ SimpleExpressionValue SimpleExpressionUnaryOperation::EvaluateStatic() const return m_operation_type->m_evaluation_function(m_operand->EvaluateStatic()); } -SimpleExpressionValue SimpleExpressionUnaryOperation::EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const +SimpleExpressionValue SimpleExpressionUnaryOperation::EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const { return m_operation_type->m_evaluation_function(m_operand->EvaluateNonStatic(scopeValues)); } diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h index e8aef4a7..18e0dcc6 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h @@ -49,5 +49,5 @@ public: _NODISCARD bool Equals(const ISimpleExpression* other) const override; _NODISCARD bool IsStatic() const override; _NODISCARD SimpleExpressionValue EvaluateStatic() const override; - _NODISCARD SimpleExpressionValue EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const override; + _NODISCARD SimpleExpressionValue EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const override; }; diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionValue.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionValue.cpp index 0059b191..14a9431c 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionValue.cpp +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionValue.cpp @@ -51,7 +51,7 @@ SimpleExpressionValue SimpleExpressionValue::EvaluateStatic() const return *this; } -SimpleExpressionValue SimpleExpressionValue::EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const +SimpleExpressionValue SimpleExpressionValue::EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const { return *this; } diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionValue.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionValue.h index 0a45cb24..a99d137d 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionValue.h +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionValue.h @@ -32,6 +32,6 @@ public: _NODISCARD bool Equals(const ISimpleExpression* other) const override; _NODISCARD bool IsStatic() const override; _NODISCARD SimpleExpressionValue EvaluateStatic() const override; - _NODISCARD SimpleExpressionValue EvaluateNonStatic(ISimpleExpressionScopeValues* scopeValues) const override; + _NODISCARD SimpleExpressionValue EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const override; _NODISCARD bool IsTruthy() const; };