WIP Technique loading

This commit is contained in:
Jan 2022-03-30 18:38:50 +02:00
parent b770360ee1
commit b5cd357014
3 changed files with 176 additions and 34 deletions

View File

@ -1,6 +1,8 @@
#include "AssetLoaderTechniqueSet.h"
#include <cstring>
#include <memory>
#include <unordered_map>
#include <sstream>
#include <type_traits>
@ -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<std::string, MaterialTechnique*> m_loaded_techniques;
IAssetLoadingManager* const m_manager;
public:
_NODISCARD MaterialTechnique* FindLoadedTechnique(const std::string& techniqueName) const
struct Pass
{
XAssetInfo<MaterialVertexShader>* m_vertex_shader;
XAssetInfo<MaterialPixelShader>* m_pixel_shader;
MaterialVertexDeclaration m_vertex_decl;
std::vector<MaterialShaderArgument> m_arguments;
Pass()
: m_vertex_shader(nullptr),
m_pixel_shader(nullptr),
m_vertex_decl{}
{
}
};
std::vector<Pass> m_passes;
std::vector<XAssetInfoGeneric*> 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<XAssetInfo<MaterialVertexShader>*>(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<XAssetInfo<MaterialPixelShader>*>(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<XAssetInfoGeneric*> m_dependencies;
LoadedTechnique(MaterialTechnique* technique, std::vector<XAssetInfoGeneric*> dependencies)
: m_technique(technique),
m_dependencies(std::move(dependencies))
{
}
};
class TechniqueZoneLoadingState final : public IZoneAssetLoaderState
{
std::unordered_map<std::string, std::unique_ptr<LoadedTechnique>> 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<XAssetInfoGeneric*> 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<LoadedTechnique>(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<XAssetInfoGeneric*>& 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<TechniqueZoneLoadingState>())
{
}
const LoadedTechnique* LoadMaterialTechnique(const std::string& techniqueName)
{
auto* technique = m_zone_state->FindLoadedTechnique(techniqueName);
if (technique)
return technique;
std::vector<XAssetInfoGeneric*> 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<TechniqueZoneLoadingState>();
TechniqueLoader techniqueLoader(searchPath, memory, manager);
std::set<XAssetInfoGeneric*> dependencies;
for (auto i = 0u; i < std::extent_v<decltype(MaterialTechniqueSet::techniques)>; i++)
{
std::string techniqueName;
if (definition.GetTechniqueByIndex(i, techniqueName))
{
auto* technique = techniqueZoneLoadingState->FindLoadedTechnique(techniqueName);
auto* technique = techniqueLoader.LoadMaterialTechnique(techniqueName);
if (!technique)
{
technique = LoadTechniqueFromRaw(techniqueName, searchPath, memory, manager);
if (technique == nullptr)
return false;
techniqueZoneLoadingState->AddLoadedTechnique(techniqueName, technique);
}
techset->techniques[i] = technique;
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<scr_string_t>());
return true;
}

View File

@ -9,9 +9,7 @@ namespace IW4
{
class AssetLoaderTechniqueSet final : public BasicAssetLoader<ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet>
{
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);

View File

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