diff --git a/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.cpp index 9bfdaedc..a2762d59 100644 --- a/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.cpp +++ b/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.cpp @@ -2,12 +2,9 @@ #include "Game/IW4/IW4.h" #include "Game/IW4/Techset/TechsetConstantsIW4.h" +#include "Techset/CommonVertexDeclCreator.h" #include "Utils/Logging/Log.h" -#include -#include -#include - using namespace IW4; namespace @@ -15,78 +12,37 @@ namespace class LoaderVertexDecl final : public AssetCreator { public: - LoaderVertexDecl(MemoryManager& memory) + explicit LoaderVertexDecl(MemoryManager& memory) : m_memory(memory) { } AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - auto* decl = m_memory.Alloc(); - decl->name = m_memory.Dup(assetName.c_str()); + const auto commonVertexDecl = techset::CreateVertexDeclFromName(assetName, commonRoutingInfos); + if (!commonVertexDecl) + return AssetCreationResult::Failure(); - size_t currentOffset = 0u; - - std::string sourceAbbreviation; - while (NextAbbreviation(assetName, sourceAbbreviation, currentOffset)) + if (commonVertexDecl->m_routing.size() > std::extent_v) { - if (decl->streamCount >= std::extent_v) - { - con::error("Failed to add vertex decl stream. Too many abbreviations: {}", assetName); - return AssetCreationResult::Failure(); - } - - std::string destinationAbbreviation; - if (!NextAbbreviation(assetName, destinationAbbreviation, currentOffset)) - { - con::error("Failed to detect vertex decl destination abbreviation: {}", assetName); - return AssetCreationResult::Failure(); - } - - const auto foundSourceAbbreviation = std::ranges::find(materialStreamSourceAbbreviation, sourceAbbreviation); - if (foundSourceAbbreviation == std::end(materialStreamSourceAbbreviation)) - { - con::error("Unknown vertex decl source abbreviation: {}", sourceAbbreviation); - return AssetCreationResult::Failure(); - } - - const auto foundDestinationAbbreviation = std::ranges::find(materialStreamDestinationAbbreviation, destinationAbbreviation); - if (foundDestinationAbbreviation == std::end(materialStreamDestinationAbbreviation)) - { - con::error("Unknown vertex decl destination abbreviation: {}", destinationAbbreviation); - return AssetCreationResult::Failure(); - } - - const auto sourceIndex = static_cast(foundSourceAbbreviation - std::begin(materialStreamSourceAbbreviation)); - const auto destinationIndex = - static_cast(foundDestinationAbbreviation - std::begin(materialStreamDestinationAbbreviation)); - - decl->routing.data[decl->streamCount].source = sourceIndex; - decl->routing.data[decl->streamCount].dest = destinationIndex; - decl->hasOptionalSource = decl->hasOptionalSource || sourceIndex >= STREAM_SRC_OPTIONAL_BEGIN; - decl->streamCount++; + con::error("Vertex declaration can only have up to {} routing entries", std::extent_v); + return AssetCreationResult::Failure(); } - return AssetCreationResult::Success(context.AddAsset(assetName, decl)); - } + auto* vertexDecl = m_memory.Alloc(); - static bool NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset) - { - if (offset >= assetName.size()) - return false; + vertexDecl->name = m_memory.Dup(assetName.c_str()); - if (offset + 1 < assetName.size() && isdigit(assetName[offset + 1])) + for (const auto& commonRoutingEntry : commonVertexDecl->m_routing) { - abbreviation = std::string(assetName, offset, 2); - offset += 2; - } - else - { - abbreviation = std::string(assetName, offset, 1); - offset += 1; + 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 true; + return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, vertexDecl))); } MemoryManager& m_memory; diff --git a/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp b/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp index 8ae26e8e..6004d5ea 100644 --- a/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp +++ b/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp @@ -1,6 +1,9 @@ #include "ObjWriterIW4.h" #include "Game/IW4/Material/MaterialJsonDumperIW4.h" +#include "Game/IW4/Techset/PixelShaderDumperIW4.h" +#include "Game/IW4/Techset/TechsetDumperIW4.h" +#include "Game/IW4/Techset/VertexShaderDumperIW4.h" #include "Game/IW4/XModel/XModelDumperIW4.h" #include "Image/ImageDumperIW4.h" #include "Leaderboard/LeaderboardJsonDumperIW4.h" @@ -13,13 +16,10 @@ #include "PhysCollmap/PhysCollmapDumperIW4.h" #include "PhysPreset/PhysPresetInfoStringDumperIW4.h" #include "RawFile/RawFileDumperIW4.h" -#include "Shader/PixelShaderDumperIW4.h" -#include "Shader/VertexShaderDumperIW4.h" #include "Sound/LoadedSoundDumperIW4.h" #include "Sound/SndCurveDumperIW4.h" #include "StringTable/StringTableDumperIW4.h" #include "StructuredDataDef/StructuredDataDefDumperIW4.h" -#include "Techset/TechsetDumperIW4.h" #include "Tracer/TracerDumperIW4.h" #include "Vehicle/VehicleDumperIW4.h" #include "Weapon/WeaponDumperIW4.h" @@ -36,9 +36,15 @@ void ObjWriter::RegisterAssetDumpers(AssetDumpingContext& context) #ifdef EXPERIMENTAL_MATERIAL_COMPILATION RegisterAssetDumper(std::make_unique()); #endif - RegisterAssetDumper(std::make_unique()); - RegisterAssetDumper(std::make_unique()); - RegisterAssetDumper(std::make_unique()); + RegisterAssetDumper(std::make_unique()); + RegisterAssetDumper(std::make_unique()); + RegisterAssetDumper(std::make_unique( +#ifdef TECHSET_DEBUG + true +#else + false +#endif + )); RegisterAssetDumper(std::make_unique()); // REGISTER_DUMPER(AssetDumpersnd_alias_list_t) RegisterAssetDumper(std::make_unique()); diff --git a/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.cpp b/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.cpp deleted file mode 100644 index 17a779ae..00000000 --- a/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "PixelShaderDumperIW4.h" - -#include "Shader/ShaderCommon.h" - -using namespace IW4; - -namespace shader -{ - void PixelShaderDumperIW4::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) - { - const auto* pixelShader = asset.Asset(); - const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(asset.m_name)); - - if (!shaderFile) - return; - - shaderFile->write(reinterpret_cast(pixelShader->prog.loadDef.program), - static_cast(pixelShader->prog.loadDef.programSize) * 4u); - } -} // namespace shader diff --git a/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.h b/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.h deleted file mode 100644 index 5e91c95c..00000000 --- a/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace shader -{ - class PixelShaderDumperIW4 final : public AbstractAssetDumper - { - protected: - void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; - }; -} // namespace shader diff --git a/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.cpp b/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.cpp deleted file mode 100644 index 9531f0e6..00000000 --- a/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "VertexShaderDumperIW4.h" - -#include "Shader/ShaderCommon.h" - -using namespace IW4; - -namespace shader -{ - void VertexShaderDumperIW4::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) - { - const auto* vertexShader = asset.Asset(); - const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(asset.m_name)); - - if (!shaderFile) - return; - - shaderFile->write(reinterpret_cast(vertexShader->prog.loadDef.program), - static_cast(vertexShader->prog.loadDef.programSize) * 4u); - } -} // namespace shader diff --git a/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.h b/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.h deleted file mode 100644 index 2b817b5d..00000000 --- a/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace shader -{ - class VertexShaderDumperIW4 final : public AbstractAssetDumper - { - protected: - void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; - }; -} // namespace shader diff --git a/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.cpp b/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.cpp deleted file mode 100644 index 1a3d8119..00000000 --- a/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.cpp +++ /dev/null @@ -1,510 +0,0 @@ -#include "TechsetDumperIW4.h" - -#include "Dumping/AbstractTextDumper.h" -#include "Game/IW4/Techset/TechsetConstantsIW4.h" -#include "Pool/GlobalAssetPool.h" -#include "Shader/D3D9ShaderAnalyser.h" -#include "Techset/CommonTechset.h" -#include "Techset/CommonTechsetDumper.h" -#include "Techset/TechniqueDumpingZoneState.h" -#include "Techset/TechsetCommon.h" -#include "Utils/Logging/Log.h" - -#include -#include -#include -#include -#include -#include - -using namespace IW4; - -namespace -{ - class TechniqueFileWriter : public AbstractTextDumper - { - void DumpStateMap() const - { - Indent(); - // TODO: Actual statemap: Maybe find all materials using this techset and try to make out rules for the flags based on the statebitstable - m_stream << "stateMap \"passthrough\"; // TODO\n"; - } - - static bool FindCodeConstantSourceAccessor(const MaterialConstantSource sourceIndexToFind, - const CodeConstantSource* codeConstantTable, - std::string& codeSourceAccessor) - { - const auto* currentCodeConst = codeConstantTable; - while (currentCodeConst->name != nullptr) - { - if (currentCodeConst->subtable != nullptr) - { - std::string accessorInSubTable; - if (FindCodeConstantSourceAccessor(sourceIndexToFind, currentCodeConst->subtable, accessorInSubTable)) - { - std::ostringstream ss; - ss << currentCodeConst->name << '.' << accessorInSubTable; - codeSourceAccessor = ss.str(); - return true; - } - } - else if (currentCodeConst->arrayCount > 0) - { - if (currentCodeConst->source <= sourceIndexToFind - && static_cast(currentCodeConst->source) + currentCodeConst->arrayCount > static_cast(sourceIndexToFind)) - { - std::ostringstream ss; - ss << currentCodeConst->name << '[' << (static_cast(sourceIndexToFind) - static_cast(currentCodeConst->source)) - << ']'; - codeSourceAccessor = ss.str(); - return true; - } - } - else if (currentCodeConst->source == sourceIndexToFind) - { - codeSourceAccessor = currentCodeConst->name; - return true; - } - - currentCodeConst++; - } - - return false; - } - - static bool FindCodeSamplerSourceAccessor(const MaterialTextureSource sourceIndexToFind, - const CodeSamplerSource* codeSamplerTable, - std::string& codeSourceAccessor) - { - const auto* currentCodeConst = codeSamplerTable; - while (currentCodeConst->name != nullptr) - { - if (currentCodeConst->subtable != nullptr) - { - std::string accessorInSubTable; - if (FindCodeSamplerSourceAccessor(sourceIndexToFind, currentCodeConst->subtable, accessorInSubTable)) - { - std::ostringstream ss; - ss << currentCodeConst->name << '.' << accessorInSubTable; - codeSourceAccessor = ss.str(); - return true; - } - } - else if (currentCodeConst->arrayCount > 0) - { - if (currentCodeConst->source <= sourceIndexToFind - && static_cast(currentCodeConst->source) + currentCodeConst->arrayCount > static_cast(sourceIndexToFind)) - { - std::ostringstream ss; - ss << currentCodeConst->name << '[' << (static_cast(sourceIndexToFind) - static_cast(currentCodeConst->source)) - << ']'; - codeSourceAccessor = ss.str(); - return true; - } - } - else if (currentCodeConst->source == sourceIndexToFind) - { - codeSourceAccessor = currentCodeConst->name; - return true; - } - - currentCodeConst++; - } - - return false; - } - - void DumpShaderArg(const MaterialShaderArgument& arg, const d3d9::ShaderInfo& shaderInfo) const - { - const auto expectedRegisterSet = - arg.type == MTL_ARG_CODE_PIXEL_SAMPLER || arg.type == MTL_ARG_MATERIAL_PIXEL_SAMPLER ? d3d9::RegisterSet::SAMPLER : d3d9::RegisterSet::FLOAT_4; - const auto targetShaderArg = std::ranges::find_if(shaderInfo.m_constants, - [arg, expectedRegisterSet](const d3d9::ShaderConstant& constant) - { - return constant.m_register_set == expectedRegisterSet && constant.m_register_index <= arg.dest - && constant.m_register_index + constant.m_register_count > arg.dest; - }); - - assert(targetShaderArg != shaderInfo.m_constants.end()); - if (targetShaderArg == shaderInfo.m_constants.end()) - { - m_stream << "// Unrecognized arg dest:" << arg.dest << " type: " << arg.type << "\n"; - return; - } - - std::string codeDestAccessor; - if (targetShaderArg->m_type_elements > 1) - { - std::ostringstream ss; - ss << targetShaderArg->m_name << '[' << (arg.dest - targetShaderArg->m_register_index) << ']'; - codeDestAccessor = ss.str(); - } - else - codeDestAccessor = targetShaderArg->m_name; - - if (arg.type == MTL_ARG_CODE_VERTEX_CONST || arg.type == MTL_ARG_CODE_PIXEL_CONST) - { - const auto sourceIndex = static_cast(arg.u.codeConst.index); - std::string codeSourceAccessor; - if (FindCodeConstantSourceAccessor(sourceIndex, s_codeConsts, codeSourceAccessor) - || FindCodeConstantSourceAccessor(sourceIndex, s_defaultCodeConsts, codeSourceAccessor)) - { - if (codeDestAccessor != codeSourceAccessor) - { - Indent(); - m_stream << codeDestAccessor << " = constant." << codeSourceAccessor << ";\n"; - } - else - { -#ifdef TECHSET_DEBUG - Indent(); - m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = constant." << codeSourceAccessor << ";\n"; -#endif - } - } - else - { - assert(false); - Indent(); - m_stream << codeDestAccessor << " = UNKNOWN;\n"; - } - } - else if (arg.type == MTL_ARG_CODE_PIXEL_SAMPLER) - { - const auto sourceIndex = static_cast(arg.u.codeSampler); - std::string codeSourceAccessor; - if (FindCodeSamplerSourceAccessor(sourceIndex, s_codeSamplers, codeSourceAccessor) - || FindCodeSamplerSourceAccessor(sourceIndex, s_defaultCodeSamplers, codeSourceAccessor)) - { - if (codeDestAccessor != codeSourceAccessor) - { - Indent(); - m_stream << codeDestAccessor << " = sampler." << codeSourceAccessor << ";\n"; - } - else - { -#ifdef TECHSET_DEBUG - Indent(); - m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = sampler." << codeSourceAccessor << ";\n"; -#endif - } - } - else - { - assert(false); - Indent(); - m_stream << codeDestAccessor << " = UNKNOWN;\n"; - } - } - else if (arg.type == MTL_ARG_LITERAL_VERTEX_CONST || arg.type == MTL_ARG_LITERAL_PIXEL_CONST) - { - if (arg.u.literalConst) - { - Indent(); - m_stream << codeDestAccessor << " = float4( " << (*arg.u.literalConst)[0] << ", " << (*arg.u.literalConst)[1] << ", " - << (*arg.u.literalConst)[2] << ", " << (*arg.u.literalConst)[3] << " );\n"; - } - } - else if (arg.type == MTL_ARG_MATERIAL_PIXEL_CONST || arg.type == MTL_ARG_MATERIAL_VERTEX_CONST || arg.type == MTL_ARG_MATERIAL_PIXEL_SAMPLER) - { - Indent(); - m_stream << codeDestAccessor << " = material."; - - const auto knownConstantName = knownConstantNames.find(arg.u.nameHash); - if (knownConstantName != knownConstantNames.end()) - { - m_stream << knownConstantName->second; - } - else - { - const auto knownMaterialTextureName = knownTextureMaps.find(arg.u.nameHash); - - if (knownMaterialTextureName != knownTextureMaps.end()) - { - m_stream << knownMaterialTextureName->second.m_name; - } - else - { - const auto shaderArgNameHash = Common::R_HashString(targetShaderArg->m_name.c_str(), 0u); - if (shaderArgNameHash == arg.u.nameHash) - m_stream << targetShaderArg->m_name; - else - m_stream << "#0x" << std::hex << arg.u.nameHash; - } - } - - m_stream << ";\n"; - } - else - { - assert(false); - } - } - - void DumpVertexShader(const MaterialPass& pass) - { - auto vertexShader = pass.vertexShader; - - if (vertexShader == nullptr || vertexShader->name == nullptr) - return; - - if (vertexShader->name[0] == ',') - { - const auto loadedVertexShaderFromOtherZone = - GameGlobalAssetPools::GetGlobalPoolsForGame(GameId::IW4)->GetAsset(&vertexShader->name[1]); - - if (loadedVertexShaderFromOtherZone == nullptr) - { - // Cannot dump when shader is referenced due to unknown constant names and unknown version - Indent(); - con::error("Cannot dump vertex shader {} due to being a referenced asset", &vertexShader->name[1]); - m_stream << std::format("// Cannot dump vertex shader {} due to being a referenced asset\n", &vertexShader->name[1]); - return; - } - vertexShader = loadedVertexShaderFromOtherZone->Asset(); - } - - const auto vertexShaderInfo = - d3d9::ShaderAnalyser::GetShaderInfo(vertexShader->prog.loadDef.program, vertexShader->prog.loadDef.programSize * sizeof(uint32_t)); - assert(vertexShaderInfo); - if (!vertexShaderInfo) - return; - - m_stream << "\n"; - Indent(); - m_stream << "vertexShader " << vertexShaderInfo->m_version_major << "." << vertexShaderInfo->m_version_minor << " \"" << vertexShader->name - << "\"\n"; - Indent(); - m_stream << "{\n"; - IncIndent(); - - if (pass.args) - { - const auto totalArgCount = - static_cast(pass.perPrimArgCount) + static_cast(pass.perObjArgCount) + static_cast(pass.stableArgCount); - for (auto i = 0u; i < totalArgCount; i++) - { - const auto& arg = pass.args[i]; - if (arg.type == MTL_ARG_MATERIAL_VERTEX_CONST || arg.type == MTL_ARG_LITERAL_VERTEX_CONST || arg.type == MTL_ARG_CODE_VERTEX_CONST) - { - DumpShaderArg(arg, *vertexShaderInfo); - } - } - } - - DecIndent(); - Indent(); - m_stream << "}\n"; - } - - void DumpPixelShader(const MaterialPass& pass) - { - auto pixelShader = pass.pixelShader; - - if (pixelShader == nullptr || pixelShader->name == nullptr) - return; - - if (pixelShader->name[0] == ',') - { - const auto loadedPixelShaderFromOtherZone = - GameGlobalAssetPools::GetGlobalPoolsForGame(GameId::IW4)->GetAsset(&pixelShader->name[1]); - - if (loadedPixelShaderFromOtherZone == nullptr) - { - // Cannot dump when shader is referenced due to unknown constant names and unknown version - Indent(); - con::error("Cannot dump pixel shader {} due to being a referenced asset", &pixelShader->name[1]); - m_stream << std::format("// Cannot dump pixel shader {} due to being a referenced asset\n", &pixelShader->name[1]); - return; - } - pixelShader = loadedPixelShaderFromOtherZone->Asset(); - } - - const auto pixelShaderInfo = - d3d9::ShaderAnalyser::GetShaderInfo(pixelShader->prog.loadDef.program, pixelShader->prog.loadDef.programSize * sizeof(uint32_t)); - assert(pixelShaderInfo); - if (!pixelShaderInfo) - return; - - m_stream << "\n"; - Indent(); - m_stream << "pixelShader " << pixelShaderInfo->m_version_major << "." << pixelShaderInfo->m_version_minor << " \"" << pixelShader->name << "\"\n"; - Indent(); - m_stream << "{\n"; - IncIndent(); - - if (pass.args) - { - const auto totalArgCount = - static_cast(pass.perPrimArgCount) + static_cast(pass.perObjArgCount) + static_cast(pass.stableArgCount); - for (auto i = 0u; i < totalArgCount; i++) - { - const auto& arg = pass.args[i]; - if (arg.type == MTL_ARG_MATERIAL_PIXEL_SAMPLER || arg.type == MTL_ARG_CODE_PIXEL_SAMPLER || arg.type == MTL_ARG_CODE_PIXEL_CONST - || arg.type == MTL_ARG_MATERIAL_PIXEL_CONST || arg.type == MTL_ARG_LITERAL_PIXEL_CONST) - { - DumpShaderArg(arg, *pixelShaderInfo); - } - } - } - - DecIndent(); - Indent(); - m_stream << "}\n"; - } - - static const char* GetStreamDestinationString(const MaterialStreamDestination_e dst) - { - const auto dstIndex = static_cast(dst); - assert(dstIndex < std::extent_v); - if (dstIndex < std::extent_v) - return materialStreamDestinationNames[dstIndex]; - return ""; - } - - static const char* GetStreamSourceString(const MaterialStreamStreamSource_e src) - { - const auto srcIndex = static_cast(src); - assert(srcIndex < std::extent_v); - if (srcIndex < std::extent_v) - return materialStreamSourceNames[srcIndex]; - return ""; - } - - void DumpVertexDecl(const MaterialPass& pass) - { - const auto* vertexDecl = pass.vertexDecl; - if (vertexDecl == nullptr) - return; - - if (vertexDecl->name && vertexDecl->name[0] == ',') - { - const auto loadedVertexDeclFromOtherZone = - GameGlobalAssetPools::GetGlobalPoolsForGame(GameId::IW4)->GetAsset(&vertexDecl->name[1]); - - if (loadedVertexDeclFromOtherZone == nullptr) - { - // Cannot dump when shader is referenced due to unknown constant names and unknown version - Indent(); - con::error("Cannot dump vertex decl {} due to being a referenced asset", &vertexDecl->name[1]); - m_stream << std::format("// Cannot dump vertex decl {} due to being a referenced asset\n", &vertexDecl->name[1]); - return; - } - vertexDecl = loadedVertexDeclFromOtherZone->Asset(); - } - - m_stream << "\n"; - -#ifdef TECHSET_DEBUG - Indent(); - m_stream << "// Decl: " << vertexDecl->name << "\n"; -#endif - - const auto streamCount = std::min(static_cast(vertexDecl->streamCount), std::extent_v); - for (auto streamIndex = 0u; streamIndex < streamCount; streamIndex++) - { - const auto& stream = vertexDecl->routing.data[streamIndex]; - Indent(); - m_stream << "vertex." << GetStreamDestinationString(static_cast(stream.dest)) << " = code." - << GetStreamSourceString(static_cast(stream.source)) << ";\n"; - } - } - - void DumpPass(const MaterialPass& pass) - { - m_stream << "{\n"; - IncIndent(); - -#ifdef TECHSET_DEBUG - for (auto i = 0u; i < 8; i++) - { - const auto mask = 1u << i; - if (pass.customSamplerFlags & mask) - { - Indent(); - m_stream << "// CUSTOM SAMPLER FLAGS: 0x" << std::hex << mask << "\n"; - } - } -#endif - - DumpStateMap(); - DumpVertexShader(pass); - DumpPixelShader(pass); - DumpVertexDecl(pass); - - DecIndent(); - m_stream << "}\n"; - } - - public: - explicit TechniqueFileWriter(std::ostream& stream) - : AbstractTextDumper(stream) - { - } - - void DumpTechnique(const MaterialTechnique* technique) - { -#ifdef TECHSET_DEBUG - if (technique->flags) - { - for (auto i = 0u; i < 16; i++) - { - const auto mask = 1u << i; - if (technique->flags & mask) - { - Indent(); - m_stream << "// TECHNIQUE FLAGS: 0x" << std::hex << mask << "\n"; - } - } - } -#endif - for (auto i = 0u; i < technique->passCount; i++) - DumpPass(technique->passArray[i]); - } - }; - - techset::CommonTechset ConvertToCommonTechset(const MaterialTechniqueSet& techset) - { - std::vector techniqueNames(std::extent_v); - - for (auto techniqueIndex = 0u; techniqueIndex < std::extent_v; techniqueIndex++) - { - const auto* technique = techset.techniques[techniqueIndex]; - if (technique && technique->name) - techniqueNames[techniqueIndex] = technique->name; - } - - return techset::CommonTechset(techset.name, std::move(techniqueNames)); - } - - void DumpTechset(const AssetDumpingContext& context, const MaterialTechniqueSet& techset) - { - static techset::CommonTechniqueTypeNames commonNames(techniqueTypeNames, std::extent_v); - const auto commonTechset = ConvertToCommonTechset(techset); - - techset::DumpCommonTechset(commonNames, context, commonTechset); - } -} // namespace - -namespace techset -{ - void DumperIW4::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) - { - const auto* techniqueSet = asset.Asset(); - DumpTechset(context, *techniqueSet); - - auto* techniqueState = context.GetZoneAssetDumperState(); - for (const auto* technique : techniqueSet->techniques) - { - if (technique && techniqueState->ShouldDumpTechnique(technique)) - { - const auto techniqueFile = context.OpenAssetFile(GetFileNameForTechniqueName(technique->name)); - if (techniqueFile) - { - TechniqueFileWriter writer(*techniqueFile); - writer.DumpTechnique(technique); - } - } - } - } -} // namespace techset diff --git a/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.h b/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.h deleted file mode 100644 index 17daac8e..00000000 --- a/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace techset -{ - class DumperIW4 final : public AbstractAssetDumper - { - protected: - void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; - }; -} // namespace techset diff --git a/src/ObjWriting/Game/T6/ObjWriterT6.cpp b/src/ObjWriting/Game/T6/ObjWriterT6.cpp index b43d4947..f4d09da2 100644 --- a/src/ObjWriting/Game/T6/ObjWriterT6.cpp +++ b/src/ObjWriting/Game/T6/ObjWriterT6.cpp @@ -2,6 +2,7 @@ #include "FontIcon/FontIconDumperT6.h" #include "Game/T6/Material/MaterialJsonDumperT6.h" +#include "Game/T6/Techset/TechsetDumperT6.h" #include "Game/T6/XModel/XModelDumperT6.h" #include "Image/ImageDumperT6.h" #include "Leaderboard/LeaderboardJsonDumperT6.h" @@ -16,7 +17,6 @@ #include "Sound/SndBankDumperT6.h" #include "Sound/SndDriverGlobalsDumperT6.h" #include "StringTable/StringTableDumperT6.h" -#include "Techset/TechsetDumperT6.h" #include "Tracer/TracerDumperT6.h" #include "Vehicle/VehicleDumperT6.h" #include "Weapon/AttachmentDumperT6.h" diff --git a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.h b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.h deleted file mode 100644 index 913d1e85..00000000 --- a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace techset -{ - class DumperT6 final : public AbstractAssetDumper - { - public: - explicit DumperT6(bool debug); - - void Dump(AssetDumpingContext& context) override; - - protected: - void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; - - private: - bool m_debug; - }; -} // namespace techset diff --git a/src/ObjWriting/Techset/CommonTechniqueDumper.cpp b/src/ObjWriting/Techset/CommonTechniqueDumper.cpp index e83bd777..31128e52 100644 --- a/src/ObjWriting/Techset/CommonTechniqueDumper.cpp +++ b/src/ObjWriting/Techset/CommonTechniqueDumper.cpp @@ -103,7 +103,7 @@ namespace if (!shader.m_name.empty()) { m_stream << std::format("// ERROR: Cannot dump shader {} as its data is not loaded\n", shader.m_name); - con::error("Technique {}: Cannot dump shader {} as its data is not loaded\n", technique.m_name, shader.m_name); + con::error("Technique {}: Cannot dump shader {} as its data is not loaded", technique.m_name, shader.m_name); } return; diff --git a/src/ObjWriting/Techset/PixelShaderDumper.cpp.template b/src/ObjWriting/Techset/PixelShaderDumper.cpp.template new file mode 100644 index 00000000..c7f95cd4 --- /dev/null +++ b/src/ObjWriting/Techset/PixelShaderDumper.cpp.template @@ -0,0 +1,46 @@ +#options GAME(IW4) + +#filename "Game/" + GAME + "/Techset/PixelShaderDumper" + GAME + ".cpp" + +#set DUMPER_HEADER "\"PixelShaderDumper" + GAME + ".h\"" + +#if GAME == "IW3" +#define FEATURE_IW3 +#define IS_DX9 +#elif GAME == "IW4" +#define FEATURE_IW4 +#define IS_DX9 +#elif GAME == "IW5" +#define FEATURE_IW5 +#define IS_DX9 +#endif + +// This file was templated. +// See PixelShaderDumper.cpp.template. +// Do not modify, changes will be lost. + +#include DUMPER_HEADER + +#include "Shader/ShaderCommon.h" + +#include + +using namespace GAME; + +#set CLASS_NAME "PixelShaderDumper" + GAME + +namespace techset +{ + void CLASS_NAME::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) + { + const auto& shader = *asset.Asset(); + const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(shader.name)); + + if (!shaderFile) + return; + + shaderFile->write(reinterpret_cast(shader.prog.loadDef.program), + static_cast(shader.prog.loadDef.programSize) + * sizeof(std::remove_pointer_t)); + } +} // namespace techset diff --git a/src/ObjWriting/Techset/PixelShaderDumper.h.template b/src/ObjWriting/Techset/PixelShaderDumper.h.template new file mode 100644 index 00000000..f0d7326a --- /dev/null +++ b/src/ObjWriting/Techset/PixelShaderDumper.h.template @@ -0,0 +1,25 @@ +#options GAME(IW4) + +#filename "Game/" + GAME + "/Techset/PixelShaderDumper" + GAME + ".h" + +#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" + +// This file was templated. +// See PixelShaderDumper.h.template. +// Do not modify, changes will be lost. + +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include GAME_HEADER + +#set CLASS_NAME "PixelShaderDumper" + GAME + +namespace techset +{ + class CLASS_NAME final : public AbstractAssetDumper + { + protected: + void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; + }; +} // namespace techset diff --git a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp b/src/ObjWriting/Techset/TechsetDumper.cpp.template similarity index 78% rename from src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp rename to src/ObjWriting/Techset/TechsetDumper.cpp.template index 63d2d4a0..fd017b9f 100644 --- a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp +++ b/src/ObjWriting/Techset/TechsetDumper.cpp.template @@ -1,19 +1,55 @@ -#include "TechsetDumperT6.h" +#options GAME(IW4, T6) + +#filename "Game/" + GAME + "/Techset/TechsetDumper" + GAME + ".cpp" + +#set DUMPER_HEADER "\"TechsetDumper" + GAME + ".h\"" +#set MATERIAL_CONSTANT_ZONE_STATE_HEADER "\"Game/" + GAME + "/Material/MaterialConstantZoneState" + GAME + ".h\"" +#set TECHSET_CONSTANTS_HEADER "\"Game/" + GAME + "/Techset/TechsetConstants" + GAME + ".h\"" + +#if GAME == "IW3" +#define FEATURE_IW3 +#define IS_DX9 +#elif GAME == "IW4" +#define FEATURE_IW4 +#define IS_DX9 +#elif GAME == "IW5" +#define FEATURE_IW5 +#define IS_DX9 +#elif GAME == "T5" +#define FEATURE_T5 +#define IS_DX9 +#elif GAME == "T6" +#define FEATURE_T6 +#define IS_DX11 +#define DUMP_SHADERS "1" +#endif + +// This file was templated. +// See TechsetDumper.cpp.template. +// Do not modify, changes will be lost. + +#include DUMPER_HEADER + +#include MATERIAL_CONSTANT_ZONE_STATE_HEADER +#include TECHSET_CONSTANTS_HEADER -#include "Game/T6/Material/MaterialConstantZoneStateT6.h" -#include "Game/T6/Techset/TechsetConstantsT6.h" -#include "Shader/ShaderCommon.h" #include "Techset/CommonTechniqueDumper.h" #include "Techset/CommonTechsetDumper.h" -#include "Techset/ShaderDumpingZoneState.h" +#include "Techset/CommonVertexDeclCreator.h" #include "Techset/TechniqueDumpingZoneState.h" +#if defined(DUMP_SHADERS) +#include "Shader/ShaderCommon.h" +#include "Techset/ShaderDumpingZoneState.h" +#endif #include +#include -using namespace T6; +using namespace GAME; namespace { +#if defined(DUMP_SHADERS) void DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader& pixelShader) { const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(pixelShader.name)); @@ -21,7 +57,12 @@ namespace if (!shaderFile) return; +#if defined(FEATURE_T6) shaderFile->write(pixelShader.prog.loadDef.program, pixelShader.prog.loadDef.programSize); +#else + shaderFile->write(reinterpret_cast(pixelShader.prog.loadDef.program), + static_cast(pixelShader.prog.loadDef.programSize) * sizeof(GfxPixelShaderLoadDef::program)); +#endif } void DumpVertexShader(const AssetDumpingContext& context, const MaterialVertexShader& vertexShader) @@ -31,7 +72,12 @@ namespace if (!shaderFile) return; +#if defined(FEATURE_T6) shaderFile->write(vertexShader.prog.loadDef.program, vertexShader.prog.loadDef.programSize); +#else + shaderFile->write(reinterpret_cast(vertexShader.prog.loadDef.program), + static_cast(vertexShader.prog.loadDef.programSize) * sizeof(GfxVertexShaderLoadDef::program)); +#endif } void DumpShaders(AssetDumpingContext& context, const MaterialTechniqueSet& techset) @@ -55,12 +101,17 @@ namespace } } } +#endif techset::CommonVertexDeclaration ConvertToCommonVertexDeclaration(const MaterialVertexDeclaration* vertexDecl) { std::vector commonRouting; +#if defined(FEATURE_IW4) + if (vertexDecl && vertexDecl->name && vertexDecl->name[0] != ',') +#else if (vertexDecl) +#endif { const auto streamCount = std::min(static_cast(vertexDecl->streamCount), std::extent_v); for (auto streamIndex = 0u; streamIndex < streamCount; streamIndex++) @@ -70,12 +121,24 @@ namespace static_cast(routing.dest)); } } +#if defined(FEATURE_IW4) + else if (vertexDecl && vertexDecl->name) + { + auto result = techset::CreateVertexDeclFromName(&vertexDecl->name[1], commonRoutingInfos); + if (result.has_value()) + return std::move(*result); + } +#endif return techset::CommonVertexDeclaration(std::move(commonRouting)); } techset::CommonShaderArg ConvertToCommonArg(const MaterialShaderArgument& arg) { +#if defined(IS_DX9) + const techset::CommonShaderArgDestination destination = {.dx9 = {.m_destination_register = arg.dest}}; + +#endif switch (arg.type) { case MTL_ARG_CODE_VERTEX_CONST: @@ -87,6 +150,7 @@ namespace .m_row_count = arg.u.codeConst.rowCount, }; const techset::CommonShaderArgValue value{.code_const_source = codeConstValue}; +#if defined(IS_DX11) const techset::CommonShaderArgLocationDx11 location{ .constant_buffer_offset = arg.location.offset, }; @@ -97,6 +161,7 @@ namespace .m_buffer = arg.buffer, } }; +#endif return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); } @@ -107,6 +172,7 @@ namespace const techset::CommonShaderArgValue value{ .name_hash = arg.u.nameHash, }; +#if defined(IS_DX11) const techset::CommonShaderArgLocationDx11 location{ .constant_buffer_offset = arg.location.offset, }; @@ -117,6 +183,7 @@ namespace .m_buffer = arg.buffer, } }; +#endif return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); } @@ -126,6 +193,7 @@ namespace const techset::CommonShaderArgValue value{ .code_sampler_source = static_cast(arg.u.codeSampler), }; +#if defined(IS_DX11) const techset::CommonShaderArgLocationDx11 location{ .texture_index = arg.location.textureIndex, .sampler_index = arg.location.samplerIndex, @@ -137,6 +205,7 @@ namespace .m_buffer = arg.buffer, } }; +#endif return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); } @@ -146,6 +215,7 @@ namespace const techset::CommonShaderArgValue value{ .name_hash = arg.u.nameHash, }; +#if defined(IS_DX11) const techset::CommonShaderArgLocationDx11 location{ .texture_index = arg.location.textureIndex, .sampler_index = arg.location.samplerIndex, @@ -157,6 +227,7 @@ namespace .m_buffer = arg.buffer, } }; +#endif return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); } @@ -176,6 +247,7 @@ namespace }; } +#if defined(IS_DX11) const techset::CommonShaderArgLocationDx11 location{ .constant_buffer_offset = arg.location.offset, }; @@ -186,6 +258,7 @@ namespace .m_buffer = arg.buffer, } }; +#endif return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); } @@ -205,7 +278,11 @@ namespace { result.m_bin = techset::CommonTechniqueShaderBin{ .m_shader_bin = vertexShader->prog.loadDef.program, +#if defined(IS_DX9) + .m_shader_bin_size = vertexShader->prog.loadDef.programSize * sizeof(std::remove_pointer_t), +#else .m_shader_bin_size = vertexShader->prog.loadDef.programSize, +#endif }; } @@ -225,7 +302,11 @@ namespace { result.m_bin = techset::CommonTechniqueShaderBin{ .m_shader_bin = pixelShader->prog.loadDef.program, +#if defined(IS_DX9) + .m_shader_bin_size = pixelShader->prog.loadDef.programSize * sizeof(std::remove_pointer_t), +#else .m_shader_bin_size = pixelShader->prog.loadDef.programSize, +#endif }; } @@ -241,11 +322,13 @@ namespace const auto& pass = technique.passArray[passIndex]; std::string comment; +#ifdef FEATURE_T6 if (debug) { comment = std::format( "MaterialType: {}; PrecompiledIndex: {}", static_cast(pass.materialType), static_cast(pass.precompiledIndex)); } +#endif techset::CommonPass commonPass(pass.customSamplerFlags, // No clue what the actual state map was @@ -279,8 +362,17 @@ namespace { const auto commonTechnique = ConvertToCommonTechnique(*technique, debug); - techset::DumpCommonTechnique( - context, commonTechnique, techset::DxVersion::DX11, commonCodeSourceInfos, commonRoutingInfos, *materialConstantState, debug); + techset::DumpCommonTechnique(context, + commonTechnique, +#if defined(IS_DX9) + techset::DxVersion::DX9, +#elif defined(IS_DX11) + techset::DxVersion::DX11, +#endif + commonCodeSourceInfos, + commonRoutingInfos, + *materialConstantState, + debug); } } } @@ -307,24 +399,28 @@ namespace } } // namespace +#set CLASS_NAME "Dumper" + GAME + namespace techset { - DumperT6::DumperT6(const bool debug) + CLASS_NAME::CLASS_NAME(const bool debug) : m_debug(debug) { } - void DumperT6::Dump(AssetDumpingContext& context) + void CLASS_NAME::Dump(AssetDumpingContext& context) { context.GetZoneAssetDumperState()->EnsureInitialized(); AbstractAssetDumper::Dump(context); } - void DumperT6::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) + void CLASS_NAME::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) { const auto* techniqueSet = asset.Asset(); DumpTechset(context, *techniqueSet); DumpTechniques(context, *techniqueSet, m_debug); +#if defined(DUMP_SHADERS) DumpShaders(context, *techniqueSet); +#endif } } // namespace techset diff --git a/src/ObjWriting/Techset/TechsetDumper.h.template b/src/ObjWriting/Techset/TechsetDumper.h.template new file mode 100644 index 00000000..fa1f0721 --- /dev/null +++ b/src/ObjWriting/Techset/TechsetDumper.h.template @@ -0,0 +1,33 @@ +#options GAME(IW4, T6) + +#filename "Game/" + GAME + "/Techset/TechsetDumper" + GAME + ".h" + +#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" + +// This file was templated. +// See TechsetDumper.h.template. +// Do not modify, changes will be lost. + +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include GAME_HEADER + +#set CLASS_NAME "Dumper" + GAME + +namespace techset +{ + class CLASS_NAME final : public AbstractAssetDumper + { + public: + explicit CLASS_NAME(bool debug); + + void Dump(AssetDumpingContext& context) override; + + protected: + void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; + + private: + bool m_debug; + }; +} // namespace techset diff --git a/src/ObjWriting/Techset/VertexShaderDumper.cpp.template b/src/ObjWriting/Techset/VertexShaderDumper.cpp.template new file mode 100644 index 00000000..cade44ba --- /dev/null +++ b/src/ObjWriting/Techset/VertexShaderDumper.cpp.template @@ -0,0 +1,46 @@ +#options GAME(IW4) + +#filename "Game/" + GAME + "/Techset/VertexShaderDumper" + GAME + ".cpp" + +#set DUMPER_HEADER "\"VertexShaderDumper" + GAME + ".h\"" + +#if GAME == "IW3" +#define FEATURE_IW3 +#define IS_DX9 +#elif GAME == "IW4" +#define FEATURE_IW4 +#define IS_DX9 +#elif GAME == "IW5" +#define FEATURE_IW5 +#define IS_DX9 +#endif + +// This file was templated. +// See VertexShaderDumper.cpp.template. +// Do not modify, changes will be lost. + +#include DUMPER_HEADER + +#include "Shader/ShaderCommon.h" + +#include + +using namespace GAME; + +#set CLASS_NAME "VertexShaderDumper" + GAME + +namespace techset +{ + void CLASS_NAME::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) + { + const auto& shader = *asset.Asset(); + const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(shader.name)); + + if (!shaderFile) + return; + + shaderFile->write(reinterpret_cast(shader.prog.loadDef.program), + static_cast(shader.prog.loadDef.programSize) + * sizeof(std::remove_pointer_t)); + } +} // namespace techset diff --git a/src/ObjWriting/Techset/VertexShaderDumper.h.template b/src/ObjWriting/Techset/VertexShaderDumper.h.template new file mode 100644 index 00000000..363bfb22 --- /dev/null +++ b/src/ObjWriting/Techset/VertexShaderDumper.h.template @@ -0,0 +1,25 @@ +#options GAME(IW4) + +#filename "Game/" + GAME + "/Techset/VertexShaderDumper" + GAME + ".h" + +#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" + +// This file was templated. +// See VertexShaderDumper.h.template. +// Do not modify, changes will be lost. + +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include GAME_HEADER + +#set CLASS_NAME "VertexShaderDumper" + GAME + +namespace techset +{ + class CLASS_NAME final : public AbstractAssetDumper + { + protected: + void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; + }; +} // namespace techset