diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp index 33711dd1..a2629e08 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp @@ -1,6 +1,8 @@ #include "AssetLoaderTechniqueSet.h" #include +#include +#include #include #include @@ -9,29 +11,185 @@ #include "Game/IW4/IW4.h" #include "Game/IW4/TechsetConstantsIW4.h" #include "Pool/GlobalAssetPool.h" +#include "Techset/TechniqueFileReader.h" #include "Techset/TechsetFileReader.h" using namespace IW4; namespace IW4 { - class TechniqueZoneLoadingState final : public IZoneAssetLoaderState + class TechniqueCreator final : public techset::ITechniqueDefinitionAcceptor { - std::map m_loaded_techniques; + IAssetLoadingManager* const m_manager; public: - _NODISCARD MaterialTechnique* FindLoadedTechnique(const std::string& techniqueName) const + struct Pass + { + XAssetInfo* m_vertex_shader; + XAssetInfo* m_pixel_shader; + MaterialVertexDeclaration m_vertex_decl; + std::vector m_arguments; + + Pass() + : m_vertex_shader(nullptr), + m_pixel_shader(nullptr), + m_vertex_decl{} + { + } + }; + + std::vector m_passes; + std::vector m_dependencies; + + explicit TechniqueCreator(IAssetLoadingManager* manager) + : m_manager(manager) + { + } + + void AcceptNextPass() override + { + m_passes.emplace_back(); + } + + void AcceptStateMap(const std::string& stateMapName) override + { + // TODO: State maps currently are not used + } + + bool AcceptVertexShader(size_t shaderVersionMajor, size_t shaderVersionMinor, const std::string& vertexShaderName, std::string& errorMessage) override + { + auto* vertexShaderDependency = m_manager->LoadDependency(ASSET_TYPE_VERTEXSHADER, vertexShaderName); + if (vertexShaderDependency == nullptr) + { + errorMessage = "Failed to load specified shader"; + return false; + } + + auto& pass = m_passes.at(m_passes.size() - 1); + pass.m_vertex_shader = reinterpret_cast*>(vertexShaderDependency); + + return true; + } + + bool AcceptPixelShader(size_t shaderVersionMajor, size_t shaderVersionMinor, const std::string& pixelShaderName, std::string& errorMessage) override + { + auto* pixelShaderDependency = m_manager->LoadDependency(ASSET_TYPE_PIXELSHADER, pixelShaderName); + if (pixelShaderDependency == nullptr) + { + errorMessage = "Failed to load specified shader"; + return false; + } + + auto& pass = m_passes.at(m_passes.size() - 1); + pass.m_pixel_shader = reinterpret_cast*>(pixelShaderDependency); + + return true; + } + + bool AcceptShaderCodeArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentCodeSource source, std::string& errorMessage) override + { + return false; + } + + bool AcceptShaderLiteralArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentLiteralSource source, std::string& errorMessage) override + { + return false; + } + + bool AcceptShaderMaterialArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentMaterialSource source, std::string& errorMessage) override + { + return false; + } + + bool AcceptVertexStreamRouting(const std::string& destination, const std::string& source, std::string& errorMessage) override + { + return false; + } + }; + + class LoadedTechnique + { + public: + MaterialTechnique* m_technique; + std::vector m_dependencies; + + LoadedTechnique(MaterialTechnique* technique, std::vector dependencies) + : m_technique(technique), + m_dependencies(std::move(dependencies)) + { + } + }; + + class TechniqueZoneLoadingState final : public IZoneAssetLoaderState + { + std::unordered_map> m_loaded_techniques; + + public: + _NODISCARD const LoadedTechnique* FindLoadedTechnique(const std::string& techniqueName) const { const auto loadedTechnique = m_loaded_techniques.find(techniqueName); if (loadedTechnique != m_loaded_techniques.end()) - return loadedTechnique->second; + return loadedTechnique->second.get(); return nullptr; } - void AddLoadedTechnique(std::string techniqueName, MaterialTechnique* technique) + const LoadedTechnique* AddLoadedTechnique(std::string techniqueName, MaterialTechnique* technique, std::vector dependencies) { - m_loaded_techniques.emplace(std::make_pair(std::move(techniqueName), technique)); + return m_loaded_techniques.emplace(std::make_pair(std::move(techniqueName), std::make_unique(technique, std::move(dependencies)))).first->second.get(); + } + }; + + class TechniqueLoader + { + ISearchPath* m_search_path; + MemoryManager* m_memory; + IAssetLoadingManager* m_manager; + TechniqueZoneLoadingState* m_zone_state; + + static std::string GetTechniqueFileName(const std::string& techniqueName) + { + std::ostringstream ss; + ss << "techniques/" << techniqueName << ".tech"; + return ss.str(); + } + + MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, std::vector& dependencies) + { + const auto techniqueFileName = GetTechniqueFileName(techniqueName); + const auto file = m_search_path->Open(techniqueFileName); + if (!file.IsOpen()) + return nullptr; + + TechniqueCreator creator(m_manager); + techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator); + if (!reader.ReadTechniqueDefinition()) + return nullptr; + // TODO: Load technique or use previously loaded one + return nullptr; + } + + public: + TechniqueLoader(ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) + : m_search_path(searchPath), + m_memory(memory), + m_manager(manager), + m_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()) + { + } + + const LoadedTechnique* LoadMaterialTechnique(const std::string& techniqueName) + { + auto* technique = m_zone_state->FindLoadedTechnique(techniqueName); + if (technique) + return technique; + + std::vector dependencies; + auto* techniqueFromRaw = LoadTechniqueFromRaw(techniqueName, dependencies); + if (technique == nullptr) + return nullptr; + + return m_zone_state->AddLoadedTechnique(techniqueName, techniqueFromRaw, dependencies); } }; } @@ -44,13 +202,6 @@ void* AssetLoaderTechniqueSet::CreateEmptyAsset(const std::string& assetName, Me return techset; } -std::string AssetLoaderTechniqueSet::GetTechniqueFileName(const std::string& techniqueName) -{ - std::ostringstream ss; - ss << "techniques/" << techniqueName << ".tech"; - return ss.str(); -} - std::string AssetLoaderTechniqueSet::GetTechsetFileName(const std::string& techsetAssetName) { std::ostringstream ss; @@ -58,13 +209,6 @@ std::string AssetLoaderTechniqueSet::GetTechsetFileName(const std::string& techs return ss.str(); } -MaterialTechnique* AssetLoaderTechniqueSet::LoadTechniqueFromRaw(const std::string& techniqueName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) -{ - const auto techniqueFileName = GetTechniqueFileName(techniqueName); - // TODO: Load technique or use previously loaded one - return nullptr; -} - bool AssetLoaderTechniqueSet::CreateTechsetFromDefinition(const std::string& assetName, const techset::TechsetDefinition& definition, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) { @@ -72,26 +216,26 @@ bool AssetLoaderTechniqueSet::CreateTechsetFromDefinition(const std::string& ass memset(techset, 0, sizeof(MaterialTechniqueSet)); techset->name = memory->Dup(assetName.c_str()); - auto* techniqueZoneLoadingState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); + TechniqueLoader techniqueLoader(searchPath, memory, manager); + std::set dependencies; for (auto i = 0u; i < std::extent_v; i++) { std::string techniqueName; if (definition.GetTechniqueByIndex(i, techniqueName)) { - auto* technique = techniqueZoneLoadingState->FindLoadedTechnique(techniqueName); - if (!technique) - { - technique = LoadTechniqueFromRaw(techniqueName, searchPath, memory, manager); - if (technique == nullptr) - return false; - techniqueZoneLoadingState->AddLoadedTechnique(techniqueName, technique); - } + auto* technique = techniqueLoader.LoadMaterialTechnique(techniqueName); - techset->techniques[i] = technique; + if (!technique) + return false; + + for (auto* techniqueDependency : technique->m_dependencies) + dependencies.emplace(techniqueDependency); + + techset->techniques[i] = technique->m_technique; } } - manager->AddAsset(ASSET_TYPE_TECHNIQUE_SET, assetName, techset); + manager->AddAsset(ASSET_TYPE_TECHNIQUE_SET, assetName, techset, std::vector(dependencies.begin(), dependencies.end()), std::vector()); return true; } diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h index 132de9d0..6660a791 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h @@ -9,9 +9,7 @@ namespace IW4 { class AssetLoaderTechniqueSet final : public BasicAssetLoader { - static std::string GetTechniqueFileName(const std::string& techniqueName); static std::string GetTechsetFileName(const std::string& techsetAssetName); - static MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); static bool CreateTechsetFromDefinition(const std::string& assetName, const techset::TechsetDefinition& definition, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); diff --git a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h index 1f1d93cd..a92a04a5 100644 --- a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h +++ b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h @@ -76,7 +76,7 @@ namespace techset virtual void AcceptStateMap(const std::string& stateMapName) = 0; virtual bool AcceptVertexShader(size_t shaderVersionMajor, size_t shaderVersionMinor, const std::string& vertexShaderName, std::string& errorMessage) = 0; - virtual bool AcceptPixelShader(size_t shaderVersionMajor, size_t shaderVersionMinor, const std::string& vertexShaderName, std::string& errorMessage) = 0; + virtual bool AcceptPixelShader(size_t shaderVersionMajor, size_t shaderVersionMinor, const std::string& pixelShaderName, std::string& errorMessage) = 0; virtual bool AcceptShaderCodeArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentCodeSource source, std::string& errorMessage) = 0; virtual bool AcceptShaderLiteralArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentLiteralSource source, std::string& errorMessage) = 0;