diff --git a/src/Common/Game/IW3/GameIW3.cpp b/src/Common/Game/IW3/GameIW3.cpp index 17771f20..b14dda08 100644 --- a/src/Common/Game/IW3/GameIW3.cpp +++ b/src/Common/Game/IW3/GameIW3.cpp @@ -18,6 +18,7 @@ namespace constexpr const char* SUB_ASSET_TYPE_NAMES[]{ "technique", + "vertexdecl", "vertexshader", "pixelshader", }; diff --git a/src/Common/Game/IW3/IW3.h b/src/Common/Game/IW3/IW3.h index ee7d6856..bfc5c489 100644 --- a/src/Common/Game/IW3/IW3.h +++ b/src/Common/Game/IW3/IW3.h @@ -53,6 +53,7 @@ namespace IW3 enum SubAssetType { SUB_ASSET_TYPE_TECHNIQUE, + SUB_ASSET_TYPE_VERTEX_DECL, SUB_ASSET_TYPE_VERTEX_SHADER, SUB_ASSET_TYPE_PIXEL_SHADER, diff --git a/src/Common/Game/T5/GameT5.cpp b/src/Common/Game/T5/GameT5.cpp index a385bac4..c54e40a4 100644 --- a/src/Common/Game/T5/GameT5.cpp +++ b/src/Common/Game/T5/GameT5.cpp @@ -21,6 +21,7 @@ namespace constexpr const char* SUB_ASSET_TYPE_NAMES[]{ "technique", + "vertexdecl", "vertexshader", "pixelshader", }; diff --git a/src/Common/Game/T5/T5.h b/src/Common/Game/T5/T5.h index 1989889b..962a87ad 100644 --- a/src/Common/Game/T5/T5.h +++ b/src/Common/Game/T5/T5.h @@ -63,6 +63,7 @@ namespace T5 enum SubAssetType { SUB_ASSET_TYPE_TECHNIQUE, + SUB_ASSET_TYPE_VERTEX_DECL, SUB_ASSET_TYPE_VERTEX_SHADER, SUB_ASSET_TYPE_PIXEL_SHADER, diff --git a/src/Common/Game/T6/GameT6.cpp b/src/Common/Game/T6/GameT6.cpp index cbb96687..1a4b6435 100644 --- a/src/Common/Game/T6/GameT6.cpp +++ b/src/Common/Game/T6/GameT6.cpp @@ -74,6 +74,7 @@ namespace constexpr const char* SUB_ASSET_TYPE_NAMES[]{ "technique", + "vertexdecl", "vertexshader", "pixelshader", }; diff --git a/src/Common/Game/T6/T6.h b/src/Common/Game/T6/T6.h index f3b052f1..47bd2ad7 100644 --- a/src/Common/Game/T6/T6.h +++ b/src/Common/Game/T6/T6.h @@ -83,6 +83,7 @@ namespace T6 enum SubAssetType { SUB_ASSET_TYPE_TECHNIQUE, + SUB_ASSET_TYPE_VERTEX_DECL, SUB_ASSET_TYPE_VERTEX_SHADER, SUB_ASSET_TYPE_PIXEL_SHADER, @@ -288,8 +289,9 @@ namespace T6 using AssetZBarrier = Asset; using SubAssetTechnique = SubAsset; - using SubAssetVertexShader = SubAsset; - using SubAssetPixelShader = SubAsset; + using SubAssetVertexDecl = SubAsset; + using SubAssetVertexShader = SubAsset; + using SubAssetPixelShader = SubAsset; } // namespace T6 DEFINE_ASSET_NAME_ACCESSOR(T6::AssetPhysPreset, name); diff --git a/src/ObjCommon/Techset/CommonTechnique.cpp b/src/ObjCommon/Techset/CommonTechnique.cpp index f0e9ae1b..d06c3f91 100644 --- a/src/ObjCommon/Techset/CommonTechnique.cpp +++ b/src/ObjCommon/Techset/CommonTechnique.cpp @@ -207,4 +207,18 @@ namespace techset return std::nullopt; } + + CommonVertexDeclaration::CommonVertexDeclaration(std::vector routing) + : m_routing(std::move(routing)) + { + } + + void CommonVertexDeclaration::SortRoutingEntries() + { + std::ranges::sort(m_routing, + [](const CommonStreamRouting& r1, const CommonStreamRouting& r2) + { + return r1.m_source < r2.m_source; + }); + } } // namespace techset diff --git a/src/ObjCommon/Techset/CommonTechnique.h b/src/ObjCommon/Techset/CommonTechnique.h index 4ae50e10..09cc2bef 100644 --- a/src/ObjCommon/Techset/CommonTechnique.h +++ b/src/ObjCommon/Techset/CommonTechnique.h @@ -234,6 +234,11 @@ namespace techset class CommonVertexDeclaration { public: + CommonVertexDeclaration() = default; + explicit CommonVertexDeclaration(std::vector routing); + + void SortRoutingEntries(); + std::vector m_routing; }; diff --git a/src/ObjCommon/Techset/CommonVertexDeclCreator.cpp b/src/ObjCommon/Techset/CommonVertexDeclCreator.cpp new file mode 100644 index 00000000..959a5875 --- /dev/null +++ b/src/ObjCommon/Techset/CommonVertexDeclCreator.cpp @@ -0,0 +1,67 @@ +#include "CommonVertexDeclCreator.h" + +#include "Utils/Logging/Log.h" + +#include + +namespace +{ + bool NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset) + { + if (offset >= assetName.size()) + return false; + + if (offset + 1 < assetName.size() && isdigit(assetName[offset + 1])) + { + abbreviation = std::string(assetName, offset, 2); + offset += 2; + } + else + { + abbreviation = std::string(assetName, offset, 1); + offset += 1; + } + + return true; + } +} // namespace + +namespace techset +{ + std::optional CreateVertexDeclFromName(const std::string& name, const CommonStreamRoutingInfos& routingInfos) + { + CommonVertexDeclaration result; + size_t currentOffset = 0u; + + std::string sourceAbbreviation; + while (NextAbbreviation(name, sourceAbbreviation, currentOffset)) + { + std::string destinationAbbreviation; + if (!NextAbbreviation(name, destinationAbbreviation, currentOffset)) + { + con::error("Failed to detect vertex decl destination abbreviation: {}", name); + return std::nullopt; + } + + const auto maybeSource = routingInfos.GetSourceByAbbreviation(sourceAbbreviation); + if (!maybeSource) + { + con::error("Unknown vertex decl source abbreviation: {}", sourceAbbreviation); + return std::nullopt; + } + + const auto maybeDestination = routingInfos.GetDestinationByAbbreviation(destinationAbbreviation); + if (!maybeDestination) + { + con::error("Unknown vertex decl destination abbreviation: {}", destinationAbbreviation); + return std::nullopt; + } + + result.m_routing.emplace_back(*maybeSource, *maybeDestination); + } + + result.SortRoutingEntries(); + + return result; + } +} // namespace techset diff --git a/src/ObjCommon/Techset/CommonVertexDeclCreator.h b/src/ObjCommon/Techset/CommonVertexDeclCreator.h new file mode 100644 index 00000000..a3e99b56 --- /dev/null +++ b/src/ObjCommon/Techset/CommonVertexDeclCreator.h @@ -0,0 +1,11 @@ +#pragma once + +#include "CommonTechnique.h" + +#include +#include + +namespace techset +{ + std::optional CreateVertexDeclFromName(const std::string& name, const CommonStreamRoutingInfos& routingInfos); +} diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp index d9681a32..5e1412e1 100644 --- a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp @@ -5,6 +5,7 @@ #include "Image/ImageIwdPostProcessor.h" #include "KeyValuePairs/KeyValuePairsCompilerT6.h" #include "Techset/TechsetCompilerT6.h" +#include "Techset/VertexDeclCompilerT6.h" #include @@ -22,6 +23,8 @@ namespace collection.AddAssetCreator(key_value_pairs::CreateCompilerT6(memory, zone, zoneDefinition.m_zone_definition, zoneStates)); collection.AddAssetCreator(techset::CreateCompilerT6(memory, searchPath)); + + collection.AddSubAssetCreator(techset::CreateVertexDeclCompilerT6(memory)); } void ConfigurePostProcessors(AssetCreatorCollection& collection, diff --git a/src/ObjCompiling/Game/T6/Techset/VertexDeclCompilerT6.cpp b/src/ObjCompiling/Game/T6/Techset/VertexDeclCompilerT6.cpp new file mode 100644 index 00000000..b01f2607 --- /dev/null +++ b/src/ObjCompiling/Game/T6/Techset/VertexDeclCompilerT6.cpp @@ -0,0 +1,57 @@ +#include "VertexDeclCompilerT6.h" + +#include "Game/T6/T6.h" +#include "Game/T6/Techset/TechsetConstantsT6.h" +#include "Techset/CommonVertexDeclCreator.h" +#include "Utils/Logging/Log.h" + +using namespace T6; + +namespace +{ + class VertexDeclCompilerT6 final : public SubAssetCreator + { + public: + explicit VertexDeclCompilerT6(MemoryManager& memory) + : m_memory(memory) + { + } + + AssetCreationResult CreateSubAsset(const std::string& subAssetName, AssetCreationContext& context) override + { + const auto commonVertexDecl = techset::CreateVertexDeclFromName(subAssetName, commonRoutingInfos); + if (!commonVertexDecl) + return AssetCreationResult::Failure(); + + if (commonVertexDecl->m_routing.size() > std::extent_v) + { + con::error("Vertex declaration can only have up to {} routing entries", std::extent_v); + return AssetCreationResult::Failure(); + } + + auto* vertexDecl = m_memory.Alloc(); + + for (const auto& commonRoutingEntry : commonVertexDecl->m_routing) + { + vertexDecl->routing.data[vertexDecl->streamCount].source = commonRoutingEntry.m_source; + vertexDecl->routing.data[vertexDecl->streamCount].dest = commonRoutingEntry.m_destination; + vertexDecl->hasOptionalSource = vertexDecl->hasOptionalSource || commonRoutingEntry.m_source >= STREAM_SRC_OPTIONAL_BEGIN; + + vertexDecl->streamCount++; + } + + return AssetCreationResult::Success(context.AddSubAsset(AssetRegistration(subAssetName, vertexDecl))); + } + + private: + MemoryManager& m_memory; + }; +} // namespace + +namespace techset +{ + std::unique_ptr CreateVertexDeclCompilerT6(MemoryManager& memory) + { + return std::make_unique(memory); + } +} // namespace techset diff --git a/src/ObjCompiling/Game/T6/Techset/VertexDeclCompilerT6.h b/src/ObjCompiling/Game/T6/Techset/VertexDeclCompilerT6.h new file mode 100644 index 00000000..434e602f --- /dev/null +++ b/src/ObjCompiling/Game/T6/Techset/VertexDeclCompilerT6.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Utils/MemoryManager.h" + +#include + +namespace techset +{ + std::unique_ptr CreateVertexDeclCompilerT6(MemoryManager& memory); +} diff --git a/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp b/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp index 22a11b2a..3b05e895 100644 --- a/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp +++ b/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp @@ -74,9 +74,7 @@ namespace } } - return techset::CommonVertexDeclaration{ - .m_routing = std::move(commonRouting), - }; + return techset::CommonVertexDeclaration(std::move(commonRouting)); } techset::CommonShaderArg ConvertToCommonArg(const MaterialShaderArgument& arg) diff --git a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp index 68eac6e3..035ada88 100644 --- a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp +++ b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp @@ -73,9 +73,7 @@ namespace } } - return techset::CommonVertexDeclaration{ - .m_routing = std::move(commonRouting), - }; + return techset::CommonVertexDeclaration(std::move(commonRouting)); } techset::CommonShaderArg ConvertToCommonArg(const MaterialShaderArgument& arg)