From a3f250fdca86aaa3efaed107d8b5e5a891df2d1e Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Fri, 27 Feb 2026 23:05:44 +0100 Subject: [PATCH] feat: compile t6 techsets --- src/ObjCompiling/Game/T6/ObjCompilerT6.cpp | 2 + .../Game/T6/Techset/TechniqueCompilerT6.cpp | 276 ++++++++ .../Game/T6/Techset/TechniqueCompilerT6.h | 12 + .../Game/T6/Techset/TechsetCompilerT6.cpp | 44 +- .../Techset/CommonShaderArgCreator.cpp | 665 ++++++++++++++++++ .../Techset/CommonShaderArgCreator.h | 62 ++ .../Techset/CommonTechniqueLoader.cpp | 46 ++ .../Techset/CommonTechniqueLoader.h | 10 +- .../Techset/CommonTechsetCache.cpp | 18 - src/ObjCompiling/Techset/CommonTechsetCache.h | 21 - .../Techset/CommonTechsetLoader.cpp | 1 - .../Techset/LiteralConstsZoneState.h | 131 ++++ .../Sequence/TechniqueNoScopeSequences.cpp | 6 +- .../Sequence/TechniquePassScopeSequences.cpp | 74 +- .../TechniqueShaderScopeSequences.cpp | 200 ++++-- .../Techset/Parsing/TechniqueFileParser.cpp | 36 +- .../Techset/Parsing/TechniqueFileParser.h | 12 +- .../Parsing/TechniqueFileParserState.cpp | 24 +- .../Parsing/TechniqueFileParserState.h | 22 +- .../StateMapFromTechniqueExtractor.cpp | 68 -- .../StateMap/StateMapFromTechniqueExtractor.h | 40 -- .../Techset/StateMap/StateMapReader.h | 5 +- .../{ => StateMap}/TechniqueStateMapCache.cpp | 0 .../{ => StateMap}/TechniqueStateMapCache.h | 7 +- .../Techset/TechniqueDefinitionAcceptor.cpp | 116 --- .../Techset/TechniqueDefinitionAcceptor.h | 100 --- .../Techset/TechniqueFileReader.cpp | 39 - .../Techset/TechniqueFileReader.h | 24 - 28 files changed, 1486 insertions(+), 575 deletions(-) create mode 100644 src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.cpp create mode 100644 src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.h create mode 100644 src/ObjCompiling/Techset/CommonShaderArgCreator.cpp create mode 100644 src/ObjCompiling/Techset/CommonShaderArgCreator.h delete mode 100644 src/ObjCompiling/Techset/CommonTechsetCache.cpp delete mode 100644 src/ObjCompiling/Techset/CommonTechsetCache.h create mode 100644 src/ObjCompiling/Techset/LiteralConstsZoneState.h delete mode 100644 src/ObjCompiling/Techset/StateMap/StateMapFromTechniqueExtractor.cpp delete mode 100644 src/ObjCompiling/Techset/StateMap/StateMapFromTechniqueExtractor.h rename src/ObjCompiling/Techset/{ => StateMap}/TechniqueStateMapCache.cpp (100%) rename src/ObjCompiling/Techset/{ => StateMap}/TechniqueStateMapCache.h (69%) delete mode 100644 src/ObjCompiling/Techset/TechniqueDefinitionAcceptor.cpp delete mode 100644 src/ObjCompiling/Techset/TechniqueDefinitionAcceptor.h delete mode 100644 src/ObjCompiling/Techset/TechniqueFileReader.cpp delete mode 100644 src/ObjCompiling/Techset/TechniqueFileReader.h diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp index 5e1412e1..7a825ec8 100644 --- a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp @@ -4,6 +4,7 @@ #include "Image/ImageIPakPostProcessor.h" #include "Image/ImageIwdPostProcessor.h" #include "KeyValuePairs/KeyValuePairsCompilerT6.h" +#include "Techset/TechniqueCompilerT6.h" #include "Techset/TechsetCompilerT6.h" #include "Techset/VertexDeclCompilerT6.h" @@ -24,6 +25,7 @@ namespace collection.AddAssetCreator(key_value_pairs::CreateCompilerT6(memory, zone, zoneDefinition.m_zone_definition, zoneStates)); collection.AddAssetCreator(techset::CreateCompilerT6(memory, searchPath)); + collection.AddSubAssetCreator(techset::CreateTechniqueCompilerT6(memory, searchPath)); collection.AddSubAssetCreator(techset::CreateVertexDeclCompilerT6(memory)); } diff --git a/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.cpp b/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.cpp new file mode 100644 index 00000000..2eb162ef --- /dev/null +++ b/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.cpp @@ -0,0 +1,276 @@ +#include "TechniqueCompilerT6.h" + +#include "Game/T6/T6.h" +#include "Game/T6/Techset/TechsetConstantsT6.h" +#include "Techset/CommonShaderArgCreator.h" +#include "Techset/CommonTechniqueLoader.h" +#include "Techset/LiteralConstsZoneState.h" +#include "Utils/StringUtils.h" + +#include +#include + +using namespace T6; + +namespace +{ + unsigned ConvertArgumentType(const techset::CommonShaderArgumentType& type) + { + if (type.m_shader_type == techset::CommonTechniqueShaderType::VERTEX) + { + switch (type.m_value_type) + { + case techset::CommonShaderValueType::LITERAL_CONST: + return MTL_ARG_LITERAL_VERTEX_CONST; + case techset::CommonShaderValueType::MATERIAL_CONST: + return MTL_ARG_MATERIAL_VERTEX_CONST; + case techset::CommonShaderValueType::CODE_CONST: + return MTL_ARG_CODE_VERTEX_CONST; + case techset::CommonShaderValueType::MATERIAL_SAMPLER: + case techset::CommonShaderValueType::CODE_SAMPLER: + default: + assert(false); + return 0; + } + } + + assert(type.m_shader_type == techset::CommonTechniqueShaderType::PIXEL); + + switch (type.m_value_type) + { + case techset::CommonShaderValueType::LITERAL_CONST: + return MTL_ARG_LITERAL_PIXEL_CONST; + case techset::CommonShaderValueType::MATERIAL_CONST: + return MTL_ARG_MATERIAL_PIXEL_CONST; + case techset::CommonShaderValueType::CODE_CONST: + return MTL_ARG_CODE_PIXEL_CONST; + case techset::CommonShaderValueType::MATERIAL_SAMPLER: + return MTL_ARG_MATERIAL_PIXEL_SAMPLER; + case techset::CommonShaderValueType::CODE_SAMPLER: + return MTL_ARG_CODE_PIXEL_SAMPLER; + default: + assert(false); + return 0; + } + } + + void ConvertArgumentValue(MaterialArgumentDef& argValue, const techset::CommonShaderArg& commonArg, MemoryManager& memory, AssetCreationContext& context) + { + switch (commonArg.m_type.m_value_type) + { + case techset::CommonShaderValueType::LITERAL_CONST: + { + const techset::LiteralConst literal(commonArg.m_value.literal_value); + argValue.literalConst = context.GetZoneAssetCreationState>().GetAllocatedLiteral(literal)->GamePtr(); + break; + } + case techset::CommonShaderValueType::CODE_CONST: + argValue.codeConst.index = static_cast(commonArg.m_value.code_const_source.m_index); + argValue.codeConst.firstRow = static_cast(commonArg.m_value.code_const_source.m_first_row); + argValue.codeConst.rowCount = static_cast(commonArg.m_value.code_const_source.m_row_count); + break; + case techset::CommonShaderValueType::CODE_SAMPLER: + argValue.codeSampler = static_cast(commonArg.m_value.code_sampler_source); + break; + case techset::CommonShaderValueType::MATERIAL_CONST: + case techset::CommonShaderValueType::MATERIAL_SAMPLER: + argValue.nameHash = static_cast(commonArg.m_value.name_hash); + break; + } + } + + void ConvertMaterialArgs(MaterialPass& pass, const techset::CommonPass& commonPass, MemoryManager& memory, AssetCreationContext& context) + { + pass.args = memory.Alloc(commonPass.m_args.size()); + + const auto frequencyCount = commonPass.GetFrequencyCounts(commonCodeSourceInfos); + + pass.perObjArgCount = static_cast(frequencyCount[std::to_underlying(techset::CommonCodeSourceUpdateFrequency::PER_OBJECT)]); + pass.perPrimArgCount = static_cast(frequencyCount[std::to_underlying(techset::CommonCodeSourceUpdateFrequency::PER_PRIM)]); + pass.stableArgCount = static_cast(frequencyCount[std::to_underlying(techset::CommonCodeSourceUpdateFrequency::RARELY)]); + + const auto commonArgCount = commonPass.m_args.size(); + for (auto argIndex = 0u; argIndex < commonArgCount; argIndex++) + { + auto& arg = pass.args[argIndex]; + const auto& commonArg = commonPass.m_args[argIndex]; + + arg.type = static_cast(ConvertArgumentType(commonArg.m_type)); + + arg.size = static_cast(commonArg.m_destination.dx11.m_size); + arg.buffer = static_cast(commonArg.m_destination.dx11.m_buffer); + + if (techset::IsConstValueType(commonArg.m_type.m_value_type)) + { + arg.location.offset = static_cast(commonArg.m_destination.dx11.m_location.constant_buffer_offset); + } + else + { + assert(techset::IsSamplerValueType(commonArg.m_type.m_value_type)); + arg.location.textureIndex = + static_cast(commonArg.m_destination.dx11.m_location.texture_index); + arg.location.samplerIndex = + static_cast(commonArg.m_destination.dx11.m_location.sampler_index); + } + + ConvertArgumentValue(arg.u, commonArg, memory, context); + } + } + + void ConvertVertexDecl(MaterialPass& pass, const techset::CommonVertexDeclaration& commonDecl, AssetCreationContext& context) + { + std::ostringstream nameStream; + for (const auto& entry : commonDecl.m_routing) + { + nameStream << commonRoutingInfos.GetSourceAbbreviation(entry.m_source); + nameStream << commonRoutingInfos.GetDestinationAbbreviation(entry.m_destination); + } + + const std::string declName(nameStream.str()); + auto* vertexDeclAsset = context.LoadSubAsset(declName); + assert(vertexDeclAsset); + pass.vertexDecl = vertexDeclAsset ? vertexDeclAsset->Asset() : nullptr; + } + + void ConvertMaterialPass(MaterialPass& pass, const techset::CommonPass& commonPass, AssetCreationContext& context, MemoryManager& memory) + { + ConvertVertexDecl(pass, commonPass.m_vertex_declaration, context); + + if (!commonPass.m_vertex_shader.m_name.empty()) + { + auto* vertexShaderAsset = context.LoadSubAsset(commonPass.m_vertex_shader.m_name); + assert(vertexShaderAsset); + pass.vertexShader = vertexShaderAsset ? vertexShaderAsset->Asset() : nullptr; + } + + if (!commonPass.m_pixel_shader.m_name.empty()) + { + auto* pixelShaderAsset = context.LoadSubAsset(commonPass.m_pixel_shader.m_name); + assert(pixelShaderAsset); + pass.pixelShader = pixelShaderAsset ? pixelShaderAsset->Asset() : nullptr; + } + + ConvertMaterialArgs(pass, commonPass, memory, context); + } + + void UpdateTechniqueFlags(MaterialTechnique& technique, const techset::CommonTechnique& commonTechnique) + { + std::string lowerTechniqueName(commonTechnique.m_name); + utils::MakeStringLowerCase(lowerTechniqueName); + + // Not a particularly cool way to do this but... + // the game actually does this :shrug: + if (lowerTechniqueName == "zprepass" || lowerTechniqueName.starts_with("pimp_technique_zprepass_") + || lowerTechniqueName.starts_with("pimp_technique_layer_zprepass_") || lowerTechniqueName.starts_with("pimp_technique_buildshadowmap_")) + { + technique.flags |= TECHNIQUE_FLAG_4; + } + } + + MaterialTechnique* ConvertTechnique(const techset::CommonTechnique& commonTechnique, AssetCreationContext& context, MemoryManager& memory) + { + const auto additionalPassCount = std::max(commonTechnique.m_passes.size(), 1uz) - 1uz; + auto* technique = static_cast(memory.AllocRaw(sizeof(MaterialTechnique) + additionalPassCount * sizeof(MaterialPass))); + + const auto passCount = static_cast(commonTechnique.m_passes.size()); + + technique->name = memory.Dup(commonTechnique.m_name.c_str()); + + // Take common flags and apply further logic + technique->flags = static_cast(commonTechnique.m_flags); + UpdateTechniqueFlags(*technique, commonTechnique); + + technique->passCount = passCount; + + for (auto passIndex = 0u; passIndex < passCount; passIndex++) + ConvertMaterialPass(technique->passArray[passIndex], commonTechnique.m_passes[passIndex], context, memory); + + return technique; + } + + class TechniqueShaderLoaderT6 final : public techset::ITechniqueShaderLoader + { + public: + explicit TechniqueShaderLoaderT6(AssetCreationContext& context) + : m_context(context) + { + } + + std::optional LoadVertexShader(const std::string& name) override + { + auto* shaderAsset = m_context.LoadSubAsset(name); + if (!shaderAsset) + return std::nullopt; + + const auto* shader = shaderAsset->Asset(); + assert(shader->prog.loadDef.program && shader->prog.loadDef.programSize > 0); + if (!shader->prog.loadDef.program || shader->prog.loadDef.programSize == 0) + return std::nullopt; + + return techset::CommonTechniqueShaderBin{ + .m_shader_bin = shader->prog.loadDef.program, + .m_shader_bin_size = shader->prog.loadDef.programSize, + }; + } + + std::optional LoadPixelShader(const std::string& name) override + { + auto* shaderAsset = m_context.LoadSubAsset(name); + if (!shaderAsset) + return std::nullopt; + + const auto* shader = shaderAsset->Asset(); + assert(shader->prog.loadDef.program && shader->prog.loadDef.programSize > 0); + if (!shader->prog.loadDef.program || shader->prog.loadDef.programSize == 0) + return std::nullopt; + + return techset::CommonTechniqueShaderBin{ + .m_shader_bin = shader->prog.loadDef.program, + .m_shader_bin_size = shader->prog.loadDef.programSize, + }; + } + + private: + AssetCreationContext& m_context; + }; + + class TechniqueCompilerT6 final : public SubAssetCreator + { + public: + TechniqueCompilerT6(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateSubAsset(const std::string& subAssetName, AssetCreationContext& context) override + { + bool failure = false; + TechniqueShaderLoaderT6 shaderLoader(context); + const auto commonShaderArgCreator = techset::CommonShaderArgCreator::CreateDx11(shaderLoader, context, commonCodeSourceInfos); + + const auto commonTechnique = + techset::LoadCommonTechnique(subAssetName, commonCodeSourceInfos, commonRoutingInfos, *commonShaderArgCreator, m_search_path, failure); + + if (!commonTechnique) + return failure ? AssetCreationResult::Failure() : AssetCreationResult::NoAction(); + + auto* convertedTechnique = ConvertTechnique(*commonTechnique, context, m_memory); + assert(convertedTechnique); + + return AssetCreationResult::Success(context.AddSubAsset(AssetRegistration(subAssetName, convertedTechnique))); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace techset +{ + std::unique_ptr CreateTechniqueCompilerT6(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace techset diff --git a/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.h b/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.h new file mode 100644 index 00000000..c859d4d0 --- /dev/null +++ b/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace techset +{ + std::unique_ptr CreateTechniqueCompilerT6(MemoryManager& memory, ISearchPath& searchPath); +} diff --git a/src/ObjCompiling/Game/T6/Techset/TechsetCompilerT6.cpp b/src/ObjCompiling/Game/T6/Techset/TechsetCompilerT6.cpp index 9a672a30..b23280fc 100644 --- a/src/ObjCompiling/Game/T6/Techset/TechsetCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/Techset/TechsetCompilerT6.cpp @@ -17,8 +17,8 @@ namespace techset::CountWorldVertFormatParameters(name, texCount, normalCount); // 0 and 1 seem to be treated equally - texCount = std::max(texCount, 1u); - normalCount = std::max(normalCount, 1u); + texCount = std::max(texCount, 1uz); + normalCount = std::max(normalCount, 1uz); if (texCount == 1 && normalCount == 1) return MTL_WORLDVERT_TEX_1_NRM_1; @@ -43,6 +43,25 @@ namespace return static_cast(0); } + MaterialType GetMaterialType(const std::string& name) + { + for (unsigned materialTypeIndex = MTL_TYPE_MODEL; materialTypeIndex < MTL_TYPE_COUNT; materialTypeIndex++) + { + if (name.starts_with(g_materialTypeInfo[materialTypeIndex].techniqueSetPrefix)) + return static_cast(materialTypeIndex); + } + + return MTL_TYPE_DEFAULT; + } + + void ApplyMaterialTypeToTechnique(MaterialTechnique& technique, const MaterialType materialType) + { + for (auto passIndex = 0u; passIndex < technique.passCount; passIndex++) + { + technique.passArray[passIndex].materialType = materialType; + } + } + MaterialTechniqueSet* ConvertTechniqueSet(const techset::CommonTechset& commonTechset, MemoryManager& memory) { auto* techset = memory.Alloc(); @@ -69,6 +88,27 @@ namespace return failure ? AssetCreationResult::Failure() : AssetCreationResult::NoAction(); auto* techset = ConvertTechniqueSet(*commonTechset, m_memory); + const auto materialType = GetMaterialType(assetName); + + for (auto techniqueIndex = 0u; techniqueIndex < std::extent_v; techniqueIndex++) + { + const auto& techniqueName = commonTechset->m_technique_names[techniqueIndex]; + if (techniqueName.empty()) + continue; + + auto* technique = context.LoadSubAsset(techniqueName); + if (!technique) + return AssetCreationResult::Failure(); + + techset->techniques[techniqueIndex] = technique->Asset(); + + // Another techset may override this for the technique + // but the game determines the material type by techset name. + // So this may just be a constraint that cannot be changed. + ApplyMaterialTypeToTechnique(*techset->techniques[techniqueIndex], materialType); + + // Precompiled index? + } return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, techset))); } diff --git a/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp b/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp new file mode 100644 index 00000000..8afff667 --- /dev/null +++ b/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp @@ -0,0 +1,665 @@ +#include "CommonShaderArgCreator.h" + +#include "Shader/D3D11ShaderAnalyser.h" +#include "Shader/D3D9ShaderAnalyser.h" +#include "Utils/Djb2.h" + +#include +#include +#include + +namespace +{ + class BaseCommonShaderArgCreator : public techset::CommonShaderArgCreator + { + public: + explicit BaseCommonShaderArgCreator(techset::ITechniqueShaderLoader& shaderLoader, techset::CommonCodeSourceInfos& commonCodeSourceInfos) + : m_shader_loader(shaderLoader), + m_common_code_source_infos(commonCodeSourceInfos), + m_shader_type(techset::CommonTechniqueShaderType::VERTEX), + m_bin{}, + m_tech_flags(0), + m_sampler_flags(0) + { + } + + result::Expected EnterShader(const techset::CommonTechniqueShaderType shaderType, const std::string& name) override + { + m_shader_type = shaderType; + + std::optional maybeShader; + if (shaderType == techset::CommonTechniqueShaderType::VERTEX) + { + maybeShader = m_shader_loader.LoadVertexShader(name); + } + else if (shaderType == techset::CommonTechniqueShaderType::PIXEL) + { + maybeShader = m_shader_loader.LoadPixelShader(name); + } + + if (!maybeShader) + return result::Unexpected("Failed to load shader"); + + m_bin = *maybeShader; + + return NoResult{}; + } + + result::Expected LeaveShader() override + { + m_bin = {}; + + return AutoCreateMissingArgs(); + } + + result::Expected AcceptShaderConstantArgument(const techset::CommonShaderArgCreatorDestination& destination, + const techset::CommonCodeConstSource codeConstSource, + const unsigned sourceIndex) override + { + techset::CommonShaderArgDestination commonDestination{}; + bool isTransposed; + std::string errorMessage; + if (!FindDestinationForConstant(commonDestination, isTransposed, errorMessage, destination)) + { + if (!errorMessage.empty()) + return result::Unexpected(std::move(errorMessage)); + + return result::Unexpected(std::format("Could not find constant shader input with name {}", destination.m_argument_name)); + } + + return AcceptShaderConstantArgument(commonDestination, isTransposed, codeConstSource, sourceIndex); + } + + result::Expected AcceptShaderSamplerArgument(const techset::CommonShaderArgCreatorDestination& destination, + const techset::CommonCodeSamplerSource codeSamplerSource) override + { + techset::CommonShaderArgDestination commonDestination{}; + std::string errorMessage; + if (!FindDestinationForSampler(commonDestination, errorMessage, destination)) + { + if (!errorMessage.empty()) + return result::Unexpected(std::move(errorMessage)); + + return result::Unexpected(std::format("Could not find sampler shader input with name {}", destination.m_argument_name)); + } + + return AcceptShaderSamplerArgument(commonDestination, codeSamplerSource); + } + + result::Expected AcceptShaderLiteralArgument(const techset::CommonShaderArgCreatorDestination& destination, + const std::array& literalValue) override + { + techset::CommonShaderArgDestination commonDestination{}; + bool isTransposed; + std::string errorMessage; + if (!FindDestinationForConstant(commonDestination, isTransposed, errorMessage, destination)) + { + if (!errorMessage.empty()) + return result::Unexpected(std::move(errorMessage)); + + return result::Unexpected(std::format("Could not find constant shader input with name {}", destination.m_argument_name)); + } + + techset::CommonShaderArgumentType argumentType{ + .m_shader_type = m_shader_type, + .m_value_type = techset::CommonShaderValueType::LITERAL_CONST, + }; + + techset::CommonShaderArgValue value{.literal_value = literalValue}; + + m_args.emplace_back(argumentType, commonDestination, value); + return NoResult{}; + } + + result::Expected AcceptShaderMaterialArgument(const techset::CommonShaderArgCreatorDestination& destination, + const unsigned nameHash) override + { + techset::CommonShaderArgumentType argumentType{ + .m_shader_type = m_shader_type, + .m_value_type = techset::CommonShaderValueType::MATERIAL_CONST, + }; + + techset::CommonShaderArgDestination commonDestination{}; + bool isTransposed; + std::string errorMessage; + if (!FindDestinationForConstant(commonDestination, isTransposed, errorMessage, destination)) + { + if (!errorMessage.empty()) + return result::Unexpected(std::move(errorMessage)); + + argumentType.m_value_type = techset::CommonShaderValueType::MATERIAL_SAMPLER; + + if (!FindDestinationForSampler(commonDestination, errorMessage, destination)) + { + if (!errorMessage.empty()) + return result::Unexpected(std::move(errorMessage)); + + return result::Unexpected(std::format("Could not find shader input with name {}", destination.m_argument_name)); + } + } + + techset::CommonShaderArgValue value{.name_hash = nameHash}; + + m_args.emplace_back(argumentType, commonDestination, value); + return NoResult{}; + } + + result::Expected AcceptShaderMaterialArgument(const techset::CommonShaderArgCreatorDestination& destination, + const std::string& nameValue) override + { + // All game's call R_HashString here which has the same implementation in all games + return AcceptShaderMaterialArgument(destination, djb2_xor_nocase(nameValue.c_str(), 0)); + } + + result::Expected FinalizePass(techset::CommonTechnique& technique, techset::CommonPass& pass) override + { + std::ranges::sort(m_args, + [this](const techset::CommonShaderArg& arg0, const techset::CommonShaderArg& arg1) -> bool + { + const auto updateFreq0 = arg0.GetFrequency(m_common_code_source_infos); + const auto updateFreq1 = arg1.GetFrequency(m_common_code_source_infos); + if (updateFreq0 != updateFreq1) + return updateFreq0 < updateFreq1; + + const auto typeNumeric0 = m_common_code_source_infos.GetArgumentTypeNumericValue(arg0.m_type); + const auto typeNumeric1 = m_common_code_source_infos.GetArgumentTypeNumericValue(arg1.m_type); + assert(typeNumeric0); + assert(typeNumeric1); + if (*typeNumeric0 != *typeNumeric1) + return *typeNumeric0 < *typeNumeric1; + + if (arg0.m_type.m_value_type == techset::CommonShaderValueType::MATERIAL_CONST + || arg0.m_type.m_value_type == techset::CommonShaderValueType::MATERIAL_SAMPLER) + { + return arg0.m_value.name_hash < arg1.m_value.name_hash; + } + + return CompareArgumentDestinations(arg0, arg1); + }); + + technique.m_flags |= m_tech_flags; + pass.m_args = std::move(m_args); + pass.m_sampler_flags |= m_sampler_flags; + + m_tech_flags = 0; + m_args = std::vector(); + m_sampler_flags = 0; + + return NoResult{}; + } + + protected: + result::Expected AcceptShaderConstantArgument(const techset::CommonShaderArgDestination& commonDestination, + const bool isTransposed, + const techset::CommonCodeConstSource codeConstSource, + const unsigned sourceIndex) + { + techset::CommonShaderArgumentType argumentType{ + .m_shader_type = m_shader_type, + .m_value_type = techset::CommonShaderValueType::CODE_CONST, + }; + + const auto maybeInfo = m_common_code_source_infos.GetInfoForCodeConstSource(codeConstSource); + if (!maybeInfo) + return result::Unexpected("Could not find info for code constant"); + + techset::CommonShaderArgCodeConstValue value{ + .m_index = 0, + .m_first_row = 0, + .m_row_count = 1, + }; + + // All matrices have a transposed version + // this checks whether this is a matrix + if (maybeInfo->transposedMatrix) + { + if (sourceIndex >= 4) + return result::Unexpected(std::format("Index for matrix code const is out of bounds: {} (must be < 4)", sourceIndex)); + + value.m_index = isTransposed ? *maybeInfo->transposedMatrix : codeConstSource; + value.m_first_row = sourceIndex; + } + else + { + const auto arrayCount = std::max(maybeInfo->arrayCount, 1u); + if (sourceIndex >= arrayCount) + return result::Unexpected(std::format("Index for code const is out of bounds: {} (must be < {})", sourceIndex, arrayCount)); + + value.m_index = codeConstSource + static_cast(sourceIndex); + value.m_first_row = 0; + } + + m_args.emplace_back(argumentType, commonDestination, techset::CommonShaderArgValue{.code_const_source = value}); + return NoResult{}; + } + + result::Expected AcceptShaderSamplerArgument(const techset::CommonShaderArgDestination& commonDestination, + const techset::CommonCodeSamplerSource codeSamplerSource) + { + techset::CommonShaderArgumentType argumentType{ + .m_shader_type = m_shader_type, + .m_value_type = techset::CommonShaderValueType::CODE_SAMPLER, + }; + + m_args.emplace_back(argumentType, commonDestination, techset::CommonShaderArgValue{.code_sampler_source = codeSamplerSource}); + return NoResult{}; + } + + [[nodiscard]] virtual size_t CompareArgumentDestinations(const techset::CommonShaderArg& arg0, const techset::CommonShaderArg& arg1) const = 0; + + [[nodiscard]] virtual bool FindDestinationForConstant(techset::CommonShaderArgDestination& commonDestination, + bool& isTransposed, + std::string& errorMessage, + const techset::CommonShaderArgCreatorDestination& input) = 0; + [[nodiscard]] virtual bool FindDestinationForSampler(techset::CommonShaderArgDestination& commonDestination, + std::string& errorMessage, + const techset::CommonShaderArgCreatorDestination& input) = 0; + + virtual result::Expected AutoCreateMissingArgs() = 0; + + techset::ITechniqueShaderLoader& m_shader_loader; + techset::CommonCodeSourceInfos& m_common_code_source_infos; + + techset::CommonTechniqueShaderType m_shader_type; + techset::CommonTechniqueShaderBin m_bin; + + std::vector m_args; + uint64_t m_tech_flags; + unsigned m_sampler_flags; + }; + + class CommonShaderArgCreatorDx9 final : public BaseCommonShaderArgCreator + { + public: + explicit CommonShaderArgCreatorDx9(techset::ITechniqueShaderLoader& shaderLoader, techset::CommonCodeSourceInfos& commonCodeSourceInfos) + : BaseCommonShaderArgCreator(shaderLoader, commonCodeSourceInfos) + { + } + + result::Expected EnterShader(const techset::CommonTechniqueShaderType shaderType, const std::string& name) override + { + auto result = BaseCommonShaderArgCreator::EnterShader(shaderType, name); + if (!result) + return std::move(result); + + m_shader_info = d3d9::ShaderAnalyser::GetShaderInfo(m_bin.m_shader_bin, m_bin.m_shader_bin_size); + if (!m_shader_info) + return result::Unexpected(std::format("Failed to analyse dx9 shader {}", name)); + + return NoResult{}; + } + + result::Expected LeaveShader() override + { + auto result = BaseCommonShaderArgCreator::LeaveShader(); + m_shader_info = nullptr; + + return std::move(result); + } + + protected: + [[nodiscard]] size_t CompareArgumentDestinations(const techset::CommonShaderArg& arg0, const techset::CommonShaderArg& arg1) const override + { + return arg0.m_destination.dx9.m_destination_register < arg1.m_destination.dx9.m_destination_register; + } + + [[nodiscard]] bool FindDestinationForConstant(techset::CommonShaderArgDestination& commonDestination, + bool& isTransposed, + std::string& errorMessage, + const techset::CommonShaderArgCreatorDestination& input) override + { + assert(m_shader_info); + // TODO + return false; + } + + [[nodiscard]] bool FindDestinationForSampler(techset::CommonShaderArgDestination& commonDestination, + std::string& errorMessage, + const techset::CommonShaderArgCreatorDestination& input) override + { + assert(m_shader_info); + // TODO + return false; + } + + result::Expected AutoCreateMissingArgs() override + { + // TODO + return NoResult{}; + } + + private: + std::unique_ptr m_shader_info; + }; + + class CommonShaderArgCreatorDx11 final : public BaseCommonShaderArgCreator + { + public: + explicit CommonShaderArgCreatorDx11(techset::ITechniqueShaderLoader& shaderLoader, techset::CommonCodeSourceInfos& commonCodeSourceInfos) + : BaseCommonShaderArgCreator(shaderLoader, commonCodeSourceInfos) + { + } + + result::Expected EnterShader(const techset::CommonTechniqueShaderType shaderType, const std::string& name) override + { + auto result = BaseCommonShaderArgCreator::EnterShader(shaderType, name); + if (!result) + return std::move(result); + + m_shader_info = d3d11::ShaderAnalyser::GetShaderInfo(m_bin.m_shader_bin, m_bin.m_shader_bin_size); + if (!m_shader_info) + return result::Unexpected(std::format("Failed to analyse dx11 shader {}", name)); + + CountShaderArgs(); + + return NoResult{}; + } + + result::Expected LeaveShader() override + { + auto result = BaseCommonShaderArgCreator::LeaveShader(); + m_shader_info = nullptr; + + return std::move(result); + } + + protected: + [[nodiscard]] size_t CompareArgumentDestinations(const techset::CommonShaderArg& arg0, const techset::CommonShaderArg& arg1) const override + { + if (arg0.m_destination.dx11.m_buffer != arg1.m_destination.dx11.m_buffer) + return arg0.m_destination.dx11.m_buffer < arg1.m_destination.dx11.m_buffer; + + return LocationComparisonValue(arg0) < LocationComparisonValue(arg1); + } + + [[nodiscard]] static size_t LocationComparisonValue(const techset::CommonShaderArg& arg) + { + switch (arg.m_type.m_value_type) + { + case techset::CommonShaderValueType::LITERAL_CONST: + case techset::CommonShaderValueType::MATERIAL_CONST: + case techset::CommonShaderValueType::CODE_CONST: + return arg.m_destination.dx11.m_location.constant_buffer_offset; + case techset::CommonShaderValueType::MATERIAL_SAMPLER: + case techset::CommonShaderValueType::CODE_SAMPLER: + return arg.m_destination.dx11.m_location.sampler_index; + default: + assert(false); + return 0; + } + } + + [[nodiscard]] bool FindDestinationForConstant(techset::CommonShaderArgDestination& commonDestination, + bool& isTransposed, + std::string& errorMessage, + const techset::CommonShaderArgCreatorDestination& input) override + { + assert(m_shader_info); + + auto bufferIndex = 0uz; + auto usedConstantIndex = 0uz; + const auto bufferCount = m_shader_info->m_constant_buffers.size(); + while (bufferIndex < bufferCount) + { + const auto& buffer = m_shader_info->m_constant_buffers[bufferIndex]; + + auto variableIterator = buffer.m_variables.begin(); + const auto variableEnd = buffer.m_variables.end(); + for (; variableIterator != variableEnd; ++variableIterator) + { + if (variableIterator->m_name == input.m_argument_name) + break; + + if (variableIterator->m_is_used) + usedConstantIndex++; + } + + if (variableIterator != variableEnd) + { + const auto variableElementCount = std::max(variableIterator->m_element_count, 1); + const auto inputArgumentIndex = input.m_argument_index.value_or(0); + if (inputArgumentIndex >= variableElementCount) + { + errorMessage = std::format("Shader variable {} only has {} elements", variableIterator->m_name, variableElementCount); + return false; + } + + const auto variableElementSize = variableIterator->m_size / variableElementCount; + commonDestination.dx11.m_location.constant_buffer_offset = variableIterator->m_offset + variableElementSize * inputArgumentIndex; + commonDestination.dx11.m_size = variableElementSize; + commonDestination.dx11.m_buffer = static_cast(bufferIndex); + isTransposed = variableIterator->m_variable_class == d3d11::VariableClass::MATRIX_COLUMNS; + + m_const_arg_added[usedConstantIndex] = true; + + return true; + } + + bufferIndex++; + } + + return false; + } + + [[nodiscard]] bool FindDestinationForSampler(techset::CommonShaderArgDestination& commonDestination, + std::string& errorMessage, + const techset::CommonShaderArgCreatorDestination& input) override + { + assert(m_shader_info); + + // Find texture and its index + size_t textureIndex = 0; + auto maybeTextureResource = m_shader_info->m_bound_resources.begin(); + const auto resourceEnd = m_shader_info->m_bound_resources.end(); + for (; maybeTextureResource != resourceEnd; ++maybeTextureResource) + { + if (maybeTextureResource->m_type != d3d11::BoundResourceType::TEXTURE) + continue; + + if (maybeTextureResource->m_name == input.m_argument_name) + break; + + textureIndex++; + } + + // Find sampler + const auto maybeSamplerResource = + std::ranges::find_if(m_shader_info->m_bound_resources, + [input](const d3d11::BoundResource& boundResource) + { + return boundResource.m_type == d3d11::BoundResourceType::SAMPLER && boundResource.m_name == input.m_argument_name; + }); + + const auto hasTextureResource = maybeTextureResource != resourceEnd; + const auto hasSamplerResource = maybeSamplerResource != resourceEnd; + + if (!hasSamplerResource && !hasTextureResource) + return false; + + if (hasSamplerResource && !hasTextureResource) + { + errorMessage = std::format("Shader binds a sampler for argument {} but not a texture", input.m_argument_name); + return false; + } + assert(hasTextureResource); + + commonDestination.dx11.m_location.texture_index = maybeTextureResource->m_bind_point; + + // The game seems to be fine with not being able to find the sampler + // and just takes the same index as the texture + if (hasSamplerResource) + commonDestination.dx11.m_location.sampler_index = maybeSamplerResource->m_bind_point; + else + commonDestination.dx11.m_location.sampler_index = maybeTextureResource->m_bind_point; + + commonDestination.dx11.m_size = maybeTextureResource->m_bind_count; + commonDestination.dx11.m_buffer = 0; + + m_texture_arg_added[textureIndex] = true; + + return true; + } + + result::Expected AutoCreateMissingArgs() override + { + size_t bufferIndex = 0; + size_t usedConstantCount = 0; + size_t textureCount = 0; + + for (const auto& buffer : m_shader_info->m_constant_buffers) + { + for (const auto& variable : buffer.m_variables) + { + if (!variable.m_is_used) + continue; + + if (m_const_arg_added[usedConstantCount++]) + continue; + + auto result = AutoCreateConstantArg(variable, bufferIndex); + if (!result) + return std::move(result); + } + + bufferIndex++; + } + + for (const auto& maybeTextureResource : m_shader_info->m_bound_resources) + { + if (maybeTextureResource.m_type != d3d11::BoundResourceType::TEXTURE) + continue; + + if (m_texture_arg_added[textureCount++]) + continue; + + const auto maybeSamplerResource = std::ranges::find_if(m_shader_info->m_bound_resources, + [maybeTextureResource](const d3d11::BoundResource& boundResource) + { + return boundResource.m_type == d3d11::BoundResourceType::SAMPLER + && boundResource.m_name == maybeTextureResource.m_name; + }); + + auto result = AutoCreateSamplerArg(maybeTextureResource, + maybeSamplerResource != m_shader_info->m_bound_resources.end() ? maybeSamplerResource->m_bind_point + : maybeTextureResource.m_bind_point); + if (!result) + return std::move(result); + } + + // TODO + return NoResult{}; + } + + private: + void CountShaderArgs() + { + size_t usedConstantCount = 0; + size_t textureCount = 0; + + for (const auto& buffer : m_shader_info->m_constant_buffers) + { + for (const auto& variable : buffer.m_variables) + { + if (variable.m_is_used) + usedConstantCount++; + } + } + + for (const auto& resource : m_shader_info->m_bound_resources) + { + if (resource.m_type == d3d11::BoundResourceType::TEXTURE) + textureCount++; + } + + m_const_arg_added = std::vector(usedConstantCount, false); + m_texture_arg_added = std::vector(textureCount, false); + } + + result::Expected AutoCreateConstantArg(const d3d11::ConstantBufferVariable& variable, const size_t bufferIndex) + { + const auto maybeCodeConst = m_common_code_source_infos.GetCodeConstSourceForAccessor(variable.m_name); + if (!maybeCodeConst) + { + // Some variables are simply not added as args for some reason + if (m_common_code_source_infos.IsArgAccessorIgnored(variable.m_name)) + return NoResult{}; + + return result::Unexpected(std::format("Missing assignment to shader constant {}", variable.m_name)); + } + + const auto constInfo = m_common_code_source_infos.GetInfoForCodeConstSource(*maybeCodeConst); + if (!constInfo) + return result::Unexpected(std::format("Missing info for code const {}", variable.m_name)); + + const auto variableElementCount = std::max(variable.m_element_count, 1); + const auto variableElementSize = variable.m_size / variableElementCount; + const auto infoArrayCount = std::max(constInfo->arrayCount, 1); + if (variableElementCount > infoArrayCount) + { + return result::Unexpected(std::format("Could not auto create argument for constant {} as it has more elements ({}) than the code constant ({})", + variable.m_name, + variableElementCount, + infoArrayCount)); + } + + techset::CommonShaderArgDestination commonDestination; + commonDestination.dx11.m_size = variableElementSize; + commonDestination.dx11.m_buffer = static_cast(bufferIndex); + const auto isTransposed = variable.m_variable_class == d3d11::VariableClass::MATRIX_COLUMNS; + for (auto elementIndex = 0u; elementIndex < variableElementCount; elementIndex++) + { + commonDestination.dx11.m_location.constant_buffer_offset = variable.m_offset + variableElementSize * elementIndex; + auto result = AcceptShaderConstantArgument(commonDestination, isTransposed, *maybeCodeConst, elementIndex); + if (!result) + return std::move(result); + } + + return NoResult{}; + } + + result::Expected AutoCreateSamplerArg(const d3d11::BoundResource& textureResource, const unsigned samplerBindPoint) + { + const auto maybeCodeSampler = m_common_code_source_infos.GetCodeSamplerSourceForAccessor(textureResource.m_name); + if (!maybeCodeSampler) + return result::Unexpected(std::format("Missing assignment to shader texture {}", textureResource.m_name)); + + techset::CommonShaderArgDestination commonDestination; + commonDestination.dx11.m_location.texture_index = textureResource.m_bind_point; + commonDestination.dx11.m_location.sampler_index = samplerBindPoint; + commonDestination.dx11.m_size = textureResource.m_bind_count; + commonDestination.dx11.m_buffer = 0; + + return AcceptShaderSamplerArgument(commonDestination, *maybeCodeSampler); + } + + std::unique_ptr m_shader_info; + std::vector m_const_arg_added; + std::vector m_texture_arg_added; + }; +} // namespace + +namespace techset +{ + CommonShaderArgCreatorDestination::CommonShaderArgCreatorDestination(std::string argumentName) + : m_argument_name(std::move(argumentName)) + { + } + + CommonShaderArgCreatorDestination::CommonShaderArgCreatorDestination(std::string argumentName, const unsigned argumentIndex) + : m_argument_name(std::move(argumentName)), + m_argument_index(argumentIndex) + { + } + + std::unique_ptr + CommonShaderArgCreator::CreateDx9(ITechniqueShaderLoader& shaderLoader, AssetCreationContext& context, CommonCodeSourceInfos& commonCodeSourceInfos) + { + return std::make_unique(shaderLoader, commonCodeSourceInfos); + } + + std::unique_ptr + CommonShaderArgCreator::CreateDx11(ITechniqueShaderLoader& shaderLoader, AssetCreationContext& context, CommonCodeSourceInfos& commonCodeSourceInfos) + { + return std::make_unique(shaderLoader, commonCodeSourceInfos); + } +} // namespace techset diff --git a/src/ObjCompiling/Techset/CommonShaderArgCreator.h b/src/ObjCompiling/Techset/CommonShaderArgCreator.h new file mode 100644 index 00000000..80ba54de --- /dev/null +++ b/src/ObjCompiling/Techset/CommonShaderArgCreator.h @@ -0,0 +1,62 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Techset/CommonTechnique.h" +#include "Utils/Result.h" + +#include +#include +#include +#include + +namespace techset +{ + class ITechniqueShaderLoader + { + public: + ITechniqueShaderLoader() = default; + virtual ~ITechniqueShaderLoader() = default; + + virtual std::optional LoadVertexShader(const std::string& name) = 0; + virtual std::optional LoadPixelShader(const std::string& name) = 0; + }; + + class CommonShaderArgCreatorDestination + { + public: + std::string m_argument_name; + std::optional m_argument_index; + + CommonShaderArgCreatorDestination() = default; + explicit CommonShaderArgCreatorDestination(std::string argumentName); + CommonShaderArgCreatorDestination(std::string argumentName, unsigned argumentIndex); + }; + + class CommonShaderArgCreator + { + public: + CommonShaderArgCreator() = default; + virtual ~CommonShaderArgCreator() = default; + + virtual result::Expected EnterShader(CommonTechniqueShaderType shaderType, const std::string& name) = 0; + virtual result::Expected LeaveShader() = 0; + + virtual result::Expected + AcceptShaderConstantArgument(const CommonShaderArgCreatorDestination& destination, CommonCodeConstSource codeConstSource, unsigned sourceIndex) = 0; + virtual result::Expected AcceptShaderSamplerArgument(const CommonShaderArgCreatorDestination& destination, + CommonCodeSamplerSource codeSamplerSource) = 0; + virtual result::Expected AcceptShaderLiteralArgument(const CommonShaderArgCreatorDestination& destination, + const std::array& literalValue) = 0; + virtual result::Expected AcceptShaderMaterialArgument(const CommonShaderArgCreatorDestination& destination, + unsigned nameHash) = 0; + virtual result::Expected AcceptShaderMaterialArgument(const CommonShaderArgCreatorDestination& destination, + const std::string& nameValue) = 0; + + virtual result::Expected FinalizePass(techset::CommonTechnique& technique, CommonPass& pass) = 0; + + static std::unique_ptr + CreateDx9(ITechniqueShaderLoader& shaderLoader, AssetCreationContext& context, CommonCodeSourceInfos& commonCodeSourceInfos); + static std::unique_ptr + CreateDx11(ITechniqueShaderLoader& shaderLoader, AssetCreationContext& context, CommonCodeSourceInfos& commonCodeSourceInfos); + }; +} // namespace techset diff --git a/src/ObjCompiling/Techset/CommonTechniqueLoader.cpp b/src/ObjCompiling/Techset/CommonTechniqueLoader.cpp index 4def5bcc..6dd21eac 100644 --- a/src/ObjCompiling/Techset/CommonTechniqueLoader.cpp +++ b/src/ObjCompiling/Techset/CommonTechniqueLoader.cpp @@ -1 +1,47 @@ #include "CommonTechniqueLoader.h" + +#include "Parsing/Impl/CommentRemovingStreamProxy.h" +#include "Parsing/Impl/ParserSingleInputStream.h" +#include "Parsing/Simple/SimpleLexer.h" +#include "Parsing/TechniqueFileParser.h" +#include "Techset/TechsetCommon.h" +#include "Utils/Logging/Log.h" + +namespace techset +{ + std::unique_ptr LoadCommonTechnique(const std::string& techniqueName, + const CommonCodeSourceInfos& codeSourceInfos, + const CommonStreamRoutingInfos& routingInfos, + CommonShaderArgCreator& commonShaderArgCreator, + ISearchPath& searchPath, + bool& failure) + { + failure = false; + + const auto fileName = GetFileNameForTechniqueName(techniqueName); + const auto techniqueFile = searchPath.Open(fileName); + if (!techniqueFile.IsOpen()) + return nullptr; + + SimpleLexer::Config lexerConfig; + lexerConfig.m_emit_new_line_tokens = false; + lexerConfig.m_read_strings = true; + lexerConfig.m_string_escape_sequences = false; + lexerConfig.m_read_integer_numbers = true; + lexerConfig.m_read_floating_point_numbers = true; + + const auto baseStream = std::make_unique(*techniqueFile.m_stream, fileName); + const auto commentProxy = std::make_unique(baseStream.get()); + const auto lexer = std::make_unique(commentProxy.get(), std::move(lexerConfig)); + + const auto parser = std::make_unique(*lexer, techniqueName, codeSourceInfos, routingInfos, commonShaderArgCreator); + + const auto success = parser->Parse(); + if (success) + return parser->GetParsingResult(); + + failure = true; + con::error("Parsing technique file \"{}\" failed!", fileName); + return nullptr; + } +} // namespace techset diff --git a/src/ObjCompiling/Techset/CommonTechniqueLoader.h b/src/ObjCompiling/Techset/CommonTechniqueLoader.h index 70722720..77772ed3 100644 --- a/src/ObjCompiling/Techset/CommonTechniqueLoader.h +++ b/src/ObjCompiling/Techset/CommonTechniqueLoader.h @@ -1,12 +1,18 @@ #pragma once #include "Asset/AssetCreationContext.h" +#include "CommonShaderArgCreator.h" #include "Techset/CommonTechnique.h" #include +#include namespace techset { - std::unique_ptr - LoadCommonTechnique(const AssetCreationContext& context, const CommonCodeSourceInfos& codeSourceInfos, const CommonStreamRoutingInfos& routingInfos); + std::unique_ptr LoadCommonTechnique(const std::string& techniqueName, + const CommonCodeSourceInfos& codeSourceInfos, + const CommonStreamRoutingInfos& routingInfos, + CommonShaderArgCreator& commonShaderArgCreator, + ISearchPath& searchPath, + bool& failure); } // namespace techset diff --git a/src/ObjCompiling/Techset/CommonTechsetCache.cpp b/src/ObjCompiling/Techset/CommonTechsetCache.cpp deleted file mode 100644 index aa089e7b..00000000 --- a/src/ObjCompiling/Techset/CommonTechsetCache.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "CommonTechsetCache.h" - -using namespace techset; - -CommonTechset* CommonTechsetCache::GetCachedTechsetDefinition(const std::string& techsetName) const -{ - const auto foundTechset = m_cache.find(techsetName); - - if (foundTechset != m_cache.end()) - return foundTechset->second.get(); - - return nullptr; -} - -void CommonTechsetCache::AddCommonTechsetToCache(std::string name, std::unique_ptr definition) -{ - m_cache.emplace(std::make_pair(std::move(name), std::move(definition))); -} diff --git a/src/ObjCompiling/Techset/CommonTechsetCache.h b/src/ObjCompiling/Techset/CommonTechsetCache.h deleted file mode 100644 index dea2a1d2..00000000 --- a/src/ObjCompiling/Techset/CommonTechsetCache.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Asset/IZoneAssetCreationState.h" -#include "Techset/CommonTechset.h" - -#include -#include -#include - -namespace techset -{ - class CommonTechsetCache final : public IZoneAssetCreationState - { - public: - [[nodiscard]] CommonTechset* GetCachedTechsetDefinition(const std::string& techsetName) const; - void AddCommonTechsetToCache(std::string name, std::unique_ptr definition); - - private: - std::unordered_map> m_cache; - }; -} // namespace techset diff --git a/src/ObjCompiling/Techset/CommonTechsetLoader.cpp b/src/ObjCompiling/Techset/CommonTechsetLoader.cpp index 407f8f80..faa78f90 100644 --- a/src/ObjCompiling/Techset/CommonTechsetLoader.cpp +++ b/src/ObjCompiling/Techset/CommonTechsetLoader.cpp @@ -9,7 +9,6 @@ #include "Utils/Logging/Log.h" #include -#include #include #include diff --git a/src/ObjCompiling/Techset/LiteralConstsZoneState.h b/src/ObjCompiling/Techset/LiteralConstsZoneState.h new file mode 100644 index 00000000..cb145132 --- /dev/null +++ b/src/ObjCompiling/Techset/LiteralConstsZoneState.h @@ -0,0 +1,131 @@ +#pragma once + +#include "Asset/IZoneAssetCreationState.h" + +#include +#include +#include + +namespace techset +{ + template class LiteralConst + { + public: + using game_ptr_t = const T (*)[4]; + + LiteralConst() = default; + + LiteralConst(T v0, T v1, T v2, T v3) + : m_value({v0, v1, v2, v3}) + { + } + + explicit LiteralConst(std::array value) + : m_value(value) + { + } + + friend bool operator<(const LiteralConst& lhs, const LiteralConst& rhs) + { + if (lhs.m_value[0] < rhs.m_value[0]) + return true; + if (lhs.m_value[0] > rhs.m_value[0]) + return false; + if (lhs.m_value[1] < rhs.m_value[1]) + return true; + if (lhs.m_value[1] > rhs.m_value[1]) + return false; + if (lhs.m_value[2] < rhs.m_value[2]) + return true; + if (lhs.m_value[2] > rhs.m_value[2]) + return false; + if (lhs.m_value[3] < rhs.m_value[3]) + return true; + if (lhs.m_value[3] > rhs.m_value[3]) + return false; + return false; + } + + friend bool operator==(const LiteralConst& lhs, const LiteralConst& rhs) + { + return lhs.m_value == rhs.m_value; + } + + friend bool operator!=(const LiteralConst& lhs, const LiteralConst& rhs) + { + return !(lhs == rhs); + } + + friend bool operator<=(const LiteralConst& lhs, const LiteralConst& rhs) + { + return !(rhs < lhs); + } + + friend bool operator>(const LiteralConst& lhs, const LiteralConst& rhs) + { + return rhs < lhs; + } + + friend bool operator>=(const LiteralConst& lhs, const LiteralConst& rhs) + { + return !(lhs < rhs); + } + + game_ptr_t GamePtr() const + { + return reinterpret_cast(m_value.data()); + } + + std::array m_value; + }; + + template struct LiteralConstHash + { + std::size_t operator()(const LiteralConst& v) const noexcept + { + std::size_t seed = 0x1DDB76B3; + seed ^= (seed << 6) + (seed >> 2) + 0x0354144B + std::hash()(v.m_value[0]); + seed ^= (seed << 6) + (seed >> 2) + 0x66847B5C + std::hash()(v.m_value[1]); + seed ^= (seed << 6) + (seed >> 2) + 0x77399D60 + std::hash()(v.m_value[2]); + seed ^= (seed << 6) + (seed >> 2) + 0x477AF9AB + std::hash()(v.m_value[3]); + return seed; + } + }; + + template class LiteralConstsZoneState : public IZoneAssetCreationState + { + public: + using literal_t = LiteralConst; + + LiteralConstsZoneState() + : m_memory(nullptr) + { + } + + void Inject(ZoneAssetCreationInjection& inject) override + { + m_memory = &inject.m_zone.Memory(); + } + + literal_t* GetAllocatedLiteral(const literal_t& literal) + { + const auto& existingEntry = m_allocated_literals.find(literal); + + if (existingEntry != m_allocated_literals.end()) + return existingEntry->second; + + auto* newLiteral = m_memory->Alloc(); + newLiteral->m_value[0] = literal.m_value[0]; + newLiteral->m_value[1] = literal.m_value[1]; + newLiteral->m_value[2] = literal.m_value[2]; + newLiteral->m_value[3] = literal.m_value[3]; + m_allocated_literals.emplace(literal, newLiteral); + + return newLiteral; + } + + private: + std::unordered_map> m_allocated_literals; + MemoryManager* m_memory; + }; +} // namespace techset diff --git a/src/ObjCompiling/Techset/Parsing/Sequence/TechniqueNoScopeSequences.cpp b/src/ObjCompiling/Techset/Parsing/Sequence/TechniqueNoScopeSequences.cpp index f94e1a71..baad556e 100644 --- a/src/ObjCompiling/Techset/Parsing/Sequence/TechniqueNoScopeSequences.cpp +++ b/src/ObjCompiling/Techset/Parsing/Sequence/TechniqueNoScopeSequences.cpp @@ -23,10 +23,8 @@ namespace techset protected: void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { - assert(state->m_in_pass == false); - state->m_in_pass = true; - - state->m_acceptor->AcceptNextPass(); + assert(!state->m_current_pass); + state->m_current_pass = CommonPass(); } }; } // namespace techset diff --git a/src/ObjCompiling/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp b/src/ObjCompiling/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp index fca643b8..e61d5292 100644 --- a/src/ObjCompiling/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp +++ b/src/ObjCompiling/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp @@ -26,20 +26,22 @@ namespace techset protected: void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { - assert(state->m_in_pass == true); + assert(state->m_current_pass); + assert(state->m_technique); - std::string errorMessage; - if (!state->m_acceptor->AcceptEndPass(errorMessage)) - throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), errorMessage); + auto finalizeResult = state->m_shader_arg_creator.FinalizePass(*state->m_technique, *state->m_current_pass); + if (!finalizeResult.has_value()) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), finalizeResult.error()); - state->m_in_pass = false; + state->m_current_pass->m_vertex_declaration.SortRoutingEntries(); + state->m_technique->m_passes.emplace_back(std::move(*state->m_current_pass)); + state->m_current_pass = std::nullopt; } }; class SequenceStateMap final : public TechniqueParser::sequence_t { - static constexpr auto CAPTURE_START = 1; - static constexpr auto CAPTURE_STATE_MAP_NAME = 2; + static constexpr auto CAPTURE_STATE_MAP_NAME = 1; public: SequenceStateMap() @@ -47,7 +49,7 @@ namespace techset const SimpleMatcherFactory create(this); AddMatchers({ - create.Keyword("stateMap").Capture(CAPTURE_START), + create.Keyword("stateMap"), create.String().Capture(CAPTURE_STATE_MAP_NAME), create.Char(';'), }); @@ -56,13 +58,9 @@ namespace techset protected: void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { - const auto& firstToken = result.NextCapture(CAPTURE_START); + assert(state->m_current_pass); - 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)); + state->m_current_pass->m_state_map = result.NextCapture(CAPTURE_STATE_MAP_NAME).StringValue(); } }; @@ -71,7 +69,7 @@ namespace techset static constexpr auto TAG_VERTEX_SHADER = 1; static constexpr auto TAG_PIXEL_SHADER = 2; - static constexpr auto CAPTURE_START = 1; + static constexpr auto CAPTURE_FIRST_TOKEN = 1; static constexpr auto CAPTURE_VERSION = 2; static constexpr auto CAPTURE_VERSION_MAJOR = 3; static constexpr auto CAPTURE_VERSION_MINOR = 4; @@ -88,7 +86,7 @@ namespace techset create.Keyword("vertexShader").Tag(TAG_VERTEX_SHADER), create.Keyword("pixelShader").Tag(TAG_PIXEL_SHADER), }) - .Capture(CAPTURE_START), + .Capture(CAPTURE_FIRST_TOKEN), create.Or({ create.And({ create.Integer().Capture(CAPTURE_VERSION_MAJOR), @@ -106,31 +104,23 @@ namespace techset protected: void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { - const auto& firstToken = result.NextCapture(CAPTURE_START); - // Don't care about shader version since it's stated in the shader bin anyway const auto& shaderNameToken = result.NextCapture(CAPTURE_SHADER_NAME); - bool acceptorResult; - std::string errorMessage; const auto shaderTag = result.NextTag(); assert(shaderTag == TAG_VERTEX_SHADER || shaderTag == TAG_PIXEL_SHADER); + if (shaderTag == TAG_VERTEX_SHADER) - { - acceptorResult = state->m_acceptor->AcceptVertexShader(shaderNameToken.StringValue(), errorMessage); - state->m_current_shader = ShaderSelector::VERTEX_SHADER; - } + state->m_current_shader_type = CommonTechniqueShaderType::VERTEX; else - { - acceptorResult = state->m_acceptor->AcceptPixelShader(shaderNameToken.StringValue(), errorMessage); - state->m_current_shader = ShaderSelector::PIXEL_SHADER; - } + state->m_current_shader_type = CommonTechniqueShaderType::PIXEL; - state->m_in_shader = true; + state->m_current_shader = CommonTechniqueShader(state->m_current_shader_type, shaderNameToken.StringValue()); - if (!acceptorResult) - throw ParsingException(firstToken.GetPos(), std::move(errorMessage)); + auto enterResult = state->m_shader_arg_creator.EnterShader(state->m_current_shader->m_type, state->m_current_shader->m_name); + if (!enterResult.has_value()) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), enterResult.error()); } }; @@ -191,13 +181,23 @@ namespace techset protected: void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { - const auto& firstToken = result.NextCapture(CAPTURE_FIRST_TOKEN); - const std::string destinationString = CreateRoutingString(result, CAPTURE_STREAM_DESTINATION_NAME, CAPTURE_STREAM_DESTINATION_INDEX); - const std::string sourceString = CreateRoutingString(result, CAPTURE_STREAM_SOURCE_NAME, CAPTURE_STREAM_SOURCE_INDEX); + assert(state->m_current_pass); - std::string errorMessage; - if (!state->m_acceptor->AcceptVertexStreamRouting(destinationString, sourceString, errorMessage)) - throw ParsingException(firstToken.GetPos(), std::move(errorMessage)); + const auto& firstToken = result.NextCapture(CAPTURE_FIRST_TOKEN); + + const std::string destinationString = CreateRoutingString(result, CAPTURE_STREAM_DESTINATION_NAME, CAPTURE_STREAM_DESTINATION_INDEX); + const auto maybeDestination = state->m_routing_infos.GetDestinationByName(destinationString); + + if (!maybeDestination.has_value()) + throw ParsingException(firstToken.GetPos(), "Unknown routing destination"); + + const std::string sourceString = CreateRoutingString(result, CAPTURE_STREAM_SOURCE_NAME, CAPTURE_STREAM_SOURCE_INDEX); + const auto maybeSource = state->m_routing_infos.GetSourceByName(sourceString); + + if (!maybeSource.has_value()) + throw ParsingException(firstToken.GetPos(), "Unknown routing source"); + + state->m_current_pass->m_vertex_declaration.m_routing.emplace_back(*maybeSource, *maybeDestination); } }; } // namespace techset diff --git a/src/ObjCompiling/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp b/src/ObjCompiling/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp index 5811a145..17dbd95c 100644 --- a/src/ObjCompiling/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp +++ b/src/ObjCompiling/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp @@ -1,6 +1,7 @@ #include "TechniqueShaderScopeSequences.h" #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" +#include "Techset/CommonShaderArgCreator.h" #include @@ -10,21 +11,34 @@ namespace techset { class SequenceEndShader final : public TechniqueParser::sequence_t { + static constexpr auto CAPTURE_FIRST_TOKEN = 1; + public: SequenceEndShader() { const SimpleMatcherFactory create(this); AddMatchers({ - create.Char('}'), + create.Char('}').Capture(CAPTURE_FIRST_TOKEN), }); } protected: void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { - assert(state->m_in_shader == true); - state->m_in_shader = false; + assert(state->m_current_pass); + assert(state->m_current_shader); + + if (state->m_current_shader_type == CommonTechniqueShaderType::VERTEX) + state->m_current_pass->m_vertex_shader = std::move(*state->m_current_shader); + else + state->m_current_pass->m_pixel_shader = std::move(*state->m_current_shader); + + state->m_current_shader = std::nullopt; + + auto leaveShaderResult = state->m_shader_arg_creator.LeaveShader(); + if (!leaveShaderResult.has_value()) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), leaveShaderResult.error()); } }; @@ -134,40 +148,126 @@ namespace techset }); } - static void ProcessCodeArgument(const TechniqueParserState* state, SequenceResult& result, ShaderArgument arg, const bool isSampler) + protected: + void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { - std::vector accessors; - while (result.HasNextCapture(CAPTURE_CODE_ACCESSOR)) - accessors.emplace_back(result.NextCapture(CAPTURE_CODE_ACCESSOR).IdentifierValue()); + assert(state->m_current_shader); - ShaderArgumentCodeSource source; - if (result.HasNextCapture(CAPTURE_CODE_INDEX)) + const auto& shaderArgumentNameToken = result.NextCapture(CAPTURE_SHADER_ARGUMENT); + + CommonShaderArgCreatorDestination destination; + if (result.HasNextCapture(CAPTURE_SHADER_INDEX)) { - const auto& codeIndexToken = result.NextCapture(CAPTURE_CODE_INDEX); - if (codeIndexToken.IntegerValue() < 0) - throw ParsingException(codeIndexToken.GetPos(), "Index cannot be negative"); - source = ShaderArgumentCodeSource(std::move(accessors), static_cast(codeIndexToken.IntegerValue())); + const auto& shaderArgumentIndexToken = result.NextCapture(CAPTURE_SHADER_INDEX); + if (shaderArgumentIndexToken.IntegerValue() < 0) + throw ParsingException(shaderArgumentIndexToken.GetPos(), "Index cannot be negative"); + const auto index = static_cast(shaderArgumentIndexToken.IntegerValue()); + destination = CommonShaderArgCreatorDestination(shaderArgumentNameToken.IdentifierValue(), index); } else - source = ShaderArgumentCodeSource(std::move(accessors)); + destination = CommonShaderArgCreatorDestination(shaderArgumentNameToken.IdentifierValue()); - std::string errorMessage; - if (!isSampler) + const auto typeTag = result.NextTag(); + assert(typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL); + + if (typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER) { - if (!state->m_acceptor->AcceptShaderConstantArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage)) - throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage)); + ProcessCodeArgument(state, result, destination, typeTag == TAG_SAMPLER); + } + else if (typeTag == TAG_LITERAL) + { + ProcessLiteralArgument(state, result, destination); } else { - if (!state->m_acceptor->AcceptShaderSamplerArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage)) - throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage)); + ProcessMaterialArgument(state, result, destination); } } - static void ProcessLiteralArgument(const TechniqueParserState* state, SequenceResult& result, ShaderArgument arg) + private: + static void ProcessCodeArgument(const TechniqueParserState* state, + SequenceResult& result, + const CommonShaderArgCreatorDestination& destination, + const bool isSampler) { - float value[4]; - for (float& i : value) + const auto accessor = GetAccessorValue(result); + + union + { + CommonCodeConstSource constSource; + CommonCodeSamplerSource samplerSource; + }; + + unsigned sourceIndex = 0u; + + if (isSampler) + { + const auto maybeSamplerSource = state->m_code_source_infos.GetCodeSamplerSourceForAccessor(accessor); + if (!maybeSamplerSource.has_value()) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Unknown code sampler"); + + samplerSource = *maybeSamplerSource; + } + else + { + const auto maybeConstSource = state->m_code_source_infos.GetCodeConstSourceForAccessor(accessor); + if (!maybeConstSource.has_value()) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Unknown code constant"); + + constSource = *maybeConstSource; + } + + if (result.HasNextCapture(CAPTURE_CODE_INDEX)) + { + if (isSampler) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Code sampler is not an array"); + + const auto& codeIndexToken = result.NextCapture(CAPTURE_CODE_INDEX); + const auto indexIntValue = codeIndexToken.IntegerValue(); + if (indexIntValue < 0) + throw ParsingException(codeIndexToken.GetPos(), "Index cannot be negative"); + + sourceIndex = static_cast(indexIntValue); + + size_t codeArraySize = state->m_code_source_infos.GetInfoForCodeConstSource(constSource)->arrayCount; + + if (codeArraySize == 0) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Code constant is not an array"); + + if (codeArraySize <= sourceIndex) + { + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), + std::format("Array overflow: Code array has size {}", codeArraySize)); + } + } + + result::Expected shaderCreatorResult(NoResult{}); + if (isSampler) + shaderCreatorResult = state->m_shader_arg_creator.AcceptShaderSamplerArgument(destination, samplerSource); + else + shaderCreatorResult = state->m_shader_arg_creator.AcceptShaderConstantArgument(destination, constSource, sourceIndex); + + if (!shaderCreatorResult.has_value()) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(shaderCreatorResult.error())); + } + + static std::string GetAccessorValue(SequenceResult& result) + { + std::ostringstream accessorStream; + + accessorStream << result.NextCapture(CAPTURE_CODE_ACCESSOR).IdentifierValue(); + while (result.HasNextCapture(CAPTURE_CODE_ACCESSOR)) + accessorStream << '.' << result.NextCapture(CAPTURE_CODE_ACCESSOR).IdentifierValue(); + + return accessorStream.str(); + } + + static void ProcessLiteralArgument(const TechniqueParserState* state, + SequenceResult& result, + const CommonShaderArgCreatorDestination& destination) + { + std::array argValue; + for (float& i : argValue) { const auto& literalValueToken = result.NextCapture(CAPTURE_LITERAL_VALUE); @@ -177,56 +277,30 @@ namespace techset i = static_cast(literalValueToken.IntegerValue()); } - const ShaderArgumentLiteralSource source(value); - std::string errorMessage; - if (!state->m_acceptor->AcceptShaderLiteralArgument(state->m_current_shader, std::move(arg), source, errorMessage)) - throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage)); + auto shaderCreatorResult = state->m_shader_arg_creator.AcceptShaderLiteralArgument(destination, argValue); + + if (!shaderCreatorResult.has_value()) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(shaderCreatorResult.error())); } - static void ProcessMaterialArgument(const TechniqueParserState* state, SequenceResult& result, ShaderArgument arg) + static void ProcessMaterialArgument(const TechniqueParserState* state, + SequenceResult& result, + const CommonShaderArgCreatorDestination& destination) { - std::string errorMessage; + result::Expected shaderCreatorResult(NoResult{}); if (result.HasNextCapture(CAPTURE_MATERIAL_HASH)) { - ShaderArgumentMaterialSource source(static_cast(result.NextCapture(CAPTURE_MATERIAL_HASH).IntegerValue())); - if (!state->m_acceptor->AcceptShaderMaterialArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage)) - throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage)); + shaderCreatorResult = state->m_shader_arg_creator.AcceptShaderMaterialArgument( + destination, static_cast(result.NextCapture(CAPTURE_MATERIAL_HASH).IntegerValue())); } else { - ShaderArgumentMaterialSource source(result.NextCapture(CAPTURE_MATERIAL_NAME).IdentifierValue()); - if (!state->m_acceptor->AcceptShaderMaterialArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage)) - throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage)); + const auto stringValue = result.NextCapture(CAPTURE_MATERIAL_NAME).IdentifierValue(); + shaderCreatorResult = state->m_shader_arg_creator.AcceptShaderMaterialArgument(destination, stringValue); } - } - protected: - void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override - { - assert(state->m_in_shader == true); - - const auto& shaderArgumentNameToken = result.NextCapture(CAPTURE_SHADER_ARGUMENT); - - ShaderArgument arg; - if (result.HasNextCapture(CAPTURE_SHADER_INDEX)) - { - const auto& shaderArgumentIndexToken = result.NextCapture(CAPTURE_SHADER_INDEX); - if (shaderArgumentIndexToken.IntegerValue() < 0) - throw ParsingException(shaderArgumentIndexToken.GetPos(), "Index cannot be negative"); - const auto index = static_cast(shaderArgumentIndexToken.IntegerValue()); - arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue(), index); - } - else - arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue()); - - const auto typeTag = result.NextTag(); - assert(typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL); - if (typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER) - ProcessCodeArgument(state, result, std::move(arg), typeTag == TAG_SAMPLER); - else if (typeTag == TAG_LITERAL) - ProcessLiteralArgument(state, result, std::move(arg)); - else - ProcessMaterialArgument(state, result, std::move(arg)); + if (!shaderCreatorResult.has_value()) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(shaderCreatorResult.error())); } }; } // namespace techset diff --git a/src/ObjCompiling/Techset/Parsing/TechniqueFileParser.cpp b/src/ObjCompiling/Techset/Parsing/TechniqueFileParser.cpp index 1032d6ed..9159ad3e 100644 --- a/src/ObjCompiling/Techset/Parsing/TechniqueFileParser.cpp +++ b/src/ObjCompiling/Techset/Parsing/TechniqueFileParser.cpp @@ -4,20 +4,30 @@ #include "Sequence/TechniquePassScopeSequences.h" #include "Sequence/TechniqueShaderScopeSequences.h" -using namespace techset; - -TechniqueParser::TechniqueParser(SimpleLexer* lexer, ITechniqueDefinitionAcceptor* acceptor) - : AbstractParser(lexer, std::make_unique(acceptor)) +namespace techset { -} + TechniqueParser::TechniqueParser(SimpleLexer& lexer, + std::string techniqueName, + const CommonCodeSourceInfos& codeSourceInfos, + const CommonStreamRoutingInfos& routingInfos, + CommonShaderArgCreator& shaderArgCreator) + : AbstractParser(&lexer, std::make_unique(std::move(techniqueName), codeSourceInfos, routingInfos, shaderArgCreator)) + { + } -const std::vector& TechniqueParser::GetTestsForState() -{ - if (m_state->m_in_shader) - return TechniqueShaderScopeSequences::GetSequences(); + std::unique_ptr TechniqueParser::GetParsingResult() const + { + return std::move(m_state->m_technique); + } - if (m_state->m_in_pass) - return TechniquePassScopeSequences::GetSequences(); + const std::vector& TechniqueParser::GetTestsForState() + { + if (m_state->m_current_shader.has_value()) + return TechniqueShaderScopeSequences::GetSequences(); - return TechniqueNoScopeSequences::GetSequences(); -} + if (m_state->m_current_pass.has_value()) + return TechniquePassScopeSequences::GetSequences(); + + return TechniqueNoScopeSequences::GetSequences(); + } +} // namespace techset diff --git a/src/ObjCompiling/Techset/Parsing/TechniqueFileParser.h b/src/ObjCompiling/Techset/Parsing/TechniqueFileParser.h index 8944f573..b0232bd0 100644 --- a/src/ObjCompiling/Techset/Parsing/TechniqueFileParser.h +++ b/src/ObjCompiling/Techset/Parsing/TechniqueFileParser.h @@ -4,15 +4,21 @@ #include "Parsing/Simple/SimpleLexer.h" #include "Parsing/Simple/SimpleParserValue.h" #include "TechniqueFileParserState.h" +#include "Techset/CommonTechnique.h" namespace techset { class TechniqueParser final : public AbstractParser { + public: + TechniqueParser(SimpleLexer& lexer, + std::string techniqueName, + const CommonCodeSourceInfos& codeSourceInfos, + const CommonStreamRoutingInfos& routingInfos, + CommonShaderArgCreator& shaderArgCreator); + [[nodiscard]] std::unique_ptr GetParsingResult() const; + protected: const std::vector& GetTestsForState() override; - - public: - TechniqueParser(SimpleLexer* lexer, ITechniqueDefinitionAcceptor* acceptor); }; } // namespace techset diff --git a/src/ObjCompiling/Techset/Parsing/TechniqueFileParserState.cpp b/src/ObjCompiling/Techset/Parsing/TechniqueFileParserState.cpp index 97cdfa52..d0a42cf9 100644 --- a/src/ObjCompiling/Techset/Parsing/TechniqueFileParserState.cpp +++ b/src/ObjCompiling/Techset/Parsing/TechniqueFileParserState.cpp @@ -1,14 +1,16 @@ #include "TechniqueFileParserState.h" -#include - -using namespace techset; - -TechniqueParserState::TechniqueParserState(ITechniqueDefinitionAcceptor* acceptor) - : m_acceptor(acceptor), - m_in_pass(false), - m_in_shader(false), - m_current_shader(ShaderSelector::VERTEX_SHADER) +namespace techset { - assert(acceptor); -} + TechniqueParserState::TechniqueParserState(std::string techniqueName, + const CommonCodeSourceInfos& codeSourceInfos, + const CommonStreamRoutingInfos& routingInfos, + CommonShaderArgCreator& shaderArgCreator) + : m_technique(std::make_unique(std::move(techniqueName))), + m_code_source_infos(codeSourceInfos), + m_routing_infos(routingInfos), + m_shader_arg_creator(shaderArgCreator), + m_current_shader_type(CommonTechniqueShaderType::VERTEX) + { + } +} // namespace techset diff --git a/src/ObjCompiling/Techset/Parsing/TechniqueFileParserState.h b/src/ObjCompiling/Techset/Parsing/TechniqueFileParserState.h index b97b143c..2e3d775c 100644 --- a/src/ObjCompiling/Techset/Parsing/TechniqueFileParserState.h +++ b/src/ObjCompiling/Techset/Parsing/TechniqueFileParserState.h @@ -1,18 +1,28 @@ #pragma once -#include "Techset/TechniqueDefinitionAcceptor.h" +#include "Techset/CommonShaderArgCreator.h" +#include "Techset/CommonTechnique.h" + +#include namespace techset { class TechniqueParserState { public: - explicit TechniqueParserState(ITechniqueDefinitionAcceptor* acceptor); + TechniqueParserState(std::string techniqueName, + const CommonCodeSourceInfos& codeSourceInfos, + const CommonStreamRoutingInfos& routingInfos, + CommonShaderArgCreator& shaderArgCreator); - ITechniqueDefinitionAcceptor* const m_acceptor; + std::unique_ptr m_technique; - bool m_in_pass; - bool m_in_shader; - ShaderSelector m_current_shader; + const CommonCodeSourceInfos& m_code_source_infos; + const CommonStreamRoutingInfos& m_routing_infos; + CommonShaderArgCreator& m_shader_arg_creator; + + std::optional m_current_pass; + std::optional m_current_shader; + CommonTechniqueShaderType m_current_shader_type; }; } // namespace techset diff --git a/src/ObjCompiling/Techset/StateMap/StateMapFromTechniqueExtractor.cpp b/src/ObjCompiling/Techset/StateMap/StateMapFromTechniqueExtractor.cpp deleted file mode 100644 index 473d08c2..00000000 --- a/src/ObjCompiling/Techset/StateMap/StateMapFromTechniqueExtractor.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#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/ObjCompiling/Techset/StateMap/StateMapFromTechniqueExtractor.h b/src/ObjCompiling/Techset/StateMap/StateMapFromTechniqueExtractor.h deleted file mode 100644 index 48f70d9d..00000000 --- a/src/ObjCompiling/Techset/StateMap/StateMapFromTechniqueExtractor.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "Techset/TechniqueDefinitionAcceptor.h" - -#include - -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; - }; -} // namespace state_map diff --git a/src/ObjCompiling/Techset/StateMap/StateMapReader.h b/src/ObjCompiling/Techset/StateMap/StateMapReader.h index f3c53161..c1bda74f 100644 --- a/src/ObjCompiling/Techset/StateMap/StateMapReader.h +++ b/src/ObjCompiling/Techset/StateMap/StateMapReader.h @@ -4,7 +4,6 @@ #include "Parsing/StateMapParserState.h" #include "StateMapDefinition.h" #include "Techset/StateMap/StateMapLayout.h" -#include "Utils/ClassUtils.h" #include #include @@ -22,7 +21,7 @@ namespace state_map public: 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; + [[nodiscard]] bool IsValidEndState(const StateMapParserState* state) const; + [[nodiscard]] std::unique_ptr ReadStateMapDefinition() const; }; } // namespace state_map diff --git a/src/ObjCompiling/Techset/TechniqueStateMapCache.cpp b/src/ObjCompiling/Techset/StateMap/TechniqueStateMapCache.cpp similarity index 100% rename from src/ObjCompiling/Techset/TechniqueStateMapCache.cpp rename to src/ObjCompiling/Techset/StateMap/TechniqueStateMapCache.cpp diff --git a/src/ObjCompiling/Techset/TechniqueStateMapCache.h b/src/ObjCompiling/Techset/StateMap/TechniqueStateMapCache.h similarity index 69% rename from src/ObjCompiling/Techset/TechniqueStateMapCache.h rename to src/ObjCompiling/Techset/StateMap/TechniqueStateMapCache.h index aaf8b245..be1d8af8 100644 --- a/src/ObjCompiling/Techset/TechniqueStateMapCache.h +++ b/src/ObjCompiling/Techset/StateMap/TechniqueStateMapCache.h @@ -1,8 +1,7 @@ #pragma once #include "Asset/IZoneAssetCreationState.h" -#include "StateMap/StateMapDefinition.h" -#include "Utils/ClassUtils.h" +#include "Techset/StateMap/StateMapDefinition.h" #include #include @@ -13,10 +12,10 @@ namespace techset class TechniqueStateMapCache final : public IZoneAssetCreationState { public: - _NODISCARD const state_map::StateMapDefinition* GetCachedStateMap(const std::string& name) const; + [[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; + [[nodiscard]] const state_map::StateMapDefinition* GetStateMapForTechnique(const std::string& techniqueName) const; void SetTechniqueUsesStateMap(std::string techniqueName, const state_map::StateMapDefinition* stateMap); private: diff --git a/src/ObjCompiling/Techset/TechniqueDefinitionAcceptor.cpp b/src/ObjCompiling/Techset/TechniqueDefinitionAcceptor.cpp deleted file mode 100644 index c576a9d3..00000000 --- a/src/ObjCompiling/Techset/TechniqueDefinitionAcceptor.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "TechniqueDefinitionAcceptor.h" - -using namespace techset; - -ShaderArgument::ShaderArgument() - : m_argument_index_specified(false), - m_argument_index(0u) -{ -} - -ShaderArgument::ShaderArgument(std::string argumentName) - : m_argument_name(std::move(argumentName)), - m_argument_index_specified(false), - m_argument_index(0u) -{ -} - -ShaderArgument::ShaderArgument(std::string argumentName, const unsigned argumentIndex) - : m_argument_name(std::move(argumentName)), - m_argument_index_specified(true), - m_argument_index(argumentIndex) -{ -} - -ShaderArgumentCodeSource::ShaderArgumentCodeSource() - : m_index_accessor_specified(false), - m_index_accessor(0u) -{ -} - -ShaderArgumentCodeSource::ShaderArgumentCodeSource(std::vector accessors) - : m_accessors(std::move(accessors)), - m_index_accessor_specified(false), - m_index_accessor(0u) -{ -} - -ShaderArgumentCodeSource::ShaderArgumentCodeSource(std::vector accessors, const unsigned indexAccessor) - : m_accessors(std::move(accessors)), - m_index_accessor_specified(true), - m_index_accessor(indexAccessor) -{ -} - -ShaderArgumentLiteralSource::ShaderArgumentLiteralSource() - : m_value{} -{ -} - -ShaderArgumentLiteralSource::ShaderArgumentLiteralSource(const float v0, const float v1, const float v2, const float v3) - : m_value{v0, v1, v2, v3} -{ -} - -ShaderArgumentLiteralSource::ShaderArgumentLiteralSource(float value[4]) - : m_value{value[0], value[1], value[2], value[3]} -{ -} - -namespace techset -{ - bool operator<(const ShaderArgumentLiteralSource& lhs, const ShaderArgumentLiteralSource& rhs) - { - if (lhs.m_value[0] < rhs.m_value[0]) - return true; - if (lhs.m_value[0] > rhs.m_value[0]) - return false; - if (lhs.m_value[1] < rhs.m_value[1]) - return true; - if (lhs.m_value[1] > rhs.m_value[1]) - return false; - if (lhs.m_value[2] < rhs.m_value[2]) - return true; - if (lhs.m_value[2] > rhs.m_value[2]) - return false; - if (lhs.m_value[3] < rhs.m_value[3]) - return true; - if (lhs.m_value[3] > rhs.m_value[3]) - return false; - return false; - } - - bool operator<=(const ShaderArgumentLiteralSource& lhs, const ShaderArgumentLiteralSource& rhs) - { - return !(rhs < lhs); - } - - bool operator>(const ShaderArgumentLiteralSource& lhs, const ShaderArgumentLiteralSource& rhs) - { - return rhs < lhs; - } - - bool operator>=(const ShaderArgumentLiteralSource& lhs, const ShaderArgumentLiteralSource& rhs) - { - return !(lhs < rhs); - } -} // namespace techset - -ShaderArgumentMaterialSource::ShaderArgumentMaterialSource() - : m_is_hash(false), - m_hash(0u) -{ -} - -ShaderArgumentMaterialSource::ShaderArgumentMaterialSource(const unsigned hash) - : m_is_hash(true), - m_hash(hash) -{ -} - -ShaderArgumentMaterialSource::ShaderArgumentMaterialSource(std::string name) - : m_is_hash(false), - m_hash(0u), - m_name(std::move(name)) -{ -} diff --git a/src/ObjCompiling/Techset/TechniqueDefinitionAcceptor.h b/src/ObjCompiling/Techset/TechniqueDefinitionAcceptor.h deleted file mode 100644 index 353c52cb..00000000 --- a/src/ObjCompiling/Techset/TechniqueDefinitionAcceptor.h +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include -#include - -namespace techset -{ - enum class ShaderSelector - { - VERTEX_SHADER, - PIXEL_SHADER - }; - - class ShaderArgument - { - public: - std::string m_argument_name; - bool m_argument_index_specified; - unsigned m_argument_index; - - ShaderArgument(); - explicit ShaderArgument(std::string argumentName); - ShaderArgument(std::string argumentName, unsigned argumentIndex); - }; - - class ShaderArgumentCodeSource - { - public: - std::vector m_accessors; - bool m_index_accessor_specified; - unsigned m_index_accessor; - - ShaderArgumentCodeSource(); - explicit ShaderArgumentCodeSource(std::vector accessors); - ShaderArgumentCodeSource(std::vector accessors, unsigned indexAccessor); - }; - - class ShaderArgumentLiteralSource - { - public: - float m_value[4]; - - ShaderArgumentLiteralSource(); - ShaderArgumentLiteralSource(float v0, float v1, float v2, float v3); - explicit ShaderArgumentLiteralSource(float value[4]); - - friend bool operator<(const ShaderArgumentLiteralSource& lhs, const ShaderArgumentLiteralSource& rhs); - friend bool operator<=(const ShaderArgumentLiteralSource& lhs, const ShaderArgumentLiteralSource& rhs); - friend bool operator>(const ShaderArgumentLiteralSource& lhs, const ShaderArgumentLiteralSource& rhs); - friend bool operator>=(const ShaderArgumentLiteralSource& lhs, const ShaderArgumentLiteralSource& rhs); - }; - - class ShaderArgumentMaterialSource - { - public: - ShaderArgumentMaterialSource(); - explicit ShaderArgumentMaterialSource(unsigned hash); - explicit ShaderArgumentMaterialSource(std::string name); - - bool m_is_hash; - unsigned m_hash; - std::string m_name; - }; - - class ITechniqueDefinitionAcceptor - { - protected: - ITechniqueDefinitionAcceptor() = default; - - public: - virtual ~ITechniqueDefinitionAcceptor() = default; - ITechniqueDefinitionAcceptor(const ITechniqueDefinitionAcceptor& other) = default; - ITechniqueDefinitionAcceptor(ITechniqueDefinitionAcceptor&& other) noexcept = default; - ITechniqueDefinitionAcceptor& operator=(const ITechniqueDefinitionAcceptor& other) = default; - ITechniqueDefinitionAcceptor& operator=(ITechniqueDefinitionAcceptor&& other) noexcept = default; - - virtual void AcceptNextPass() = 0; - virtual bool AcceptEndPass(std::string& errorMessage) = 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; - - virtual bool - AcceptShaderConstantArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentCodeSource source, std::string& errorMessage) = 0; - virtual bool - AcceptShaderSamplerArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentCodeSource source, std::string& errorMessage) = 0; - virtual bool AcceptShaderLiteralArgument(ShaderSelector shader, - ShaderArgument shaderArgument, - ShaderArgumentLiteralSource source, - std::string& errorMessage) = 0; - virtual bool AcceptShaderMaterialArgument(ShaderSelector shader, - ShaderArgument shaderArgument, - ShaderArgumentMaterialSource source, - std::string& errorMessage) = 0; - - virtual bool AcceptVertexStreamRouting(const std::string& destination, const std::string& source, std::string& errorMessage) = 0; - }; -} // namespace techset diff --git a/src/ObjCompiling/Techset/TechniqueFileReader.cpp b/src/ObjCompiling/Techset/TechniqueFileReader.cpp deleted file mode 100644 index 884b9b32..00000000 --- a/src/ObjCompiling/Techset/TechniqueFileReader.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "TechniqueFileReader.h" - -#include "Parsing/Impl/CommentRemovingStreamProxy.h" -#include "Parsing/Impl/ParserSingleInputStream.h" -#include "Parsing/Simple/SimpleLexer.h" -#include "Techset/Parsing/TechniqueFileParser.h" -#include "Utils/Logging/Log.h" - -#include - -using namespace techset; - -TechniqueFileReader::TechniqueFileReader(std::istream& stream, std::string fileName, ITechniqueDefinitionAcceptor* acceptor) - : m_file_name(std::move(fileName)), - m_acceptor(acceptor) -{ - m_base_stream = std::make_unique(stream, m_file_name); - m_comment_proxy = std::make_unique(m_base_stream.get()); -} - -bool TechniqueFileReader::ReadTechniqueDefinition() const -{ - SimpleLexer::Config lexerConfig; - lexerConfig.m_emit_new_line_tokens = false; - lexerConfig.m_read_strings = true; - lexerConfig.m_string_escape_sequences = false; - lexerConfig.m_read_integer_numbers = true; - lexerConfig.m_read_floating_point_numbers = true; - const auto lexer = std::make_unique(m_comment_proxy.get(), std::move(lexerConfig)); - - const auto parser = std::make_unique(lexer.get(), m_acceptor); - - const auto success = parser->Parse(); - if (success) - return true; - - con::error("Parsing technique file \"{}\" failed!", m_file_name); - return false; -} diff --git a/src/ObjCompiling/Techset/TechniqueFileReader.h b/src/ObjCompiling/Techset/TechniqueFileReader.h deleted file mode 100644 index 9f72828e..00000000 --- a/src/ObjCompiling/Techset/TechniqueFileReader.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "Parsing/IParserLineStream.h" -#include "TechniqueDefinitionAcceptor.h" - -#include -#include - -namespace techset -{ - class TechniqueFileReader - { - public: - TechniqueFileReader(std::istream& stream, std::string fileName, ITechniqueDefinitionAcceptor* acceptor); - - [[nodiscard]] bool ReadTechniqueDefinition() const; - - private: - std::string m_file_name; - ITechniqueDefinitionAcceptor* m_acceptor; - std::unique_ptr m_base_stream; - std::unique_ptr m_comment_proxy; - }; -} // namespace techset