mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-03-15 17:33:03 +00:00
feat: template techset and shader dumping for IW4,T6
This commit is contained in:
@@ -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<material::DecompilingGdtDumperIW4>());
|
||||
#endif
|
||||
RegisterAssetDumper(std::make_unique<shader::PixelShaderDumperIW4>());
|
||||
RegisterAssetDumper(std::make_unique<shader::VertexShaderDumperIW4>());
|
||||
RegisterAssetDumper(std::make_unique<techset::DumperIW4>());
|
||||
RegisterAssetDumper(std::make_unique<techset::PixelShaderDumperIW4>());
|
||||
RegisterAssetDumper(std::make_unique<techset::VertexShaderDumperIW4>());
|
||||
RegisterAssetDumper(std::make_unique<techset::DumperIW4>(
|
||||
#ifdef TECHSET_DEBUG
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
));
|
||||
RegisterAssetDumper(std::make_unique<image::DumperIW4>());
|
||||
// REGISTER_DUMPER(AssetDumpersnd_alias_list_t)
|
||||
RegisterAssetDumper(std::make_unique<sound_curve::DumperIW4>());
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#include "PixelShaderDumperIW4.h"
|
||||
|
||||
#include "Shader/ShaderCommon.h"
|
||||
|
||||
using namespace IW4;
|
||||
|
||||
namespace shader
|
||||
{
|
||||
void PixelShaderDumperIW4::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetPixelShader::Type>& asset)
|
||||
{
|
||||
const auto* pixelShader = asset.Asset();
|
||||
const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(asset.m_name));
|
||||
|
||||
if (!shaderFile)
|
||||
return;
|
||||
|
||||
shaderFile->write(reinterpret_cast<const char*>(pixelShader->prog.loadDef.program),
|
||||
static_cast<std::streamsize>(pixelShader->prog.loadDef.programSize) * 4u);
|
||||
}
|
||||
} // namespace shader
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/IW4/IW4.h"
|
||||
|
||||
namespace shader
|
||||
{
|
||||
class PixelShaderDumperIW4 final : public AbstractAssetDumper<IW4::AssetPixelShader>
|
||||
{
|
||||
protected:
|
||||
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW4::AssetPixelShader::Type>& asset) override;
|
||||
};
|
||||
} // namespace shader
|
||||
@@ -1,20 +0,0 @@
|
||||
#include "VertexShaderDumperIW4.h"
|
||||
|
||||
#include "Shader/ShaderCommon.h"
|
||||
|
||||
using namespace IW4;
|
||||
|
||||
namespace shader
|
||||
{
|
||||
void VertexShaderDumperIW4::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetVertexShader::Type>& asset)
|
||||
{
|
||||
const auto* vertexShader = asset.Asset();
|
||||
const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(asset.m_name));
|
||||
|
||||
if (!shaderFile)
|
||||
return;
|
||||
|
||||
shaderFile->write(reinterpret_cast<const char*>(vertexShader->prog.loadDef.program),
|
||||
static_cast<std::streamsize>(vertexShader->prog.loadDef.programSize) * 4u);
|
||||
}
|
||||
} // namespace shader
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/IW4/IW4.h"
|
||||
|
||||
namespace shader
|
||||
{
|
||||
class VertexShaderDumperIW4 final : public AbstractAssetDumper<IW4::AssetVertexShader>
|
||||
{
|
||||
protected:
|
||||
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW4::AssetVertexShader::Type>& asset) override;
|
||||
};
|
||||
} // namespace shader
|
||||
@@ -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 <algorithm>
|
||||
#include <cassert>
|
||||
#include <format>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
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<unsigned>(currentCodeConst->source) + currentCodeConst->arrayCount > static_cast<unsigned>(sourceIndexToFind))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << currentCodeConst->name << '[' << (static_cast<unsigned>(sourceIndexToFind) - static_cast<unsigned>(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<unsigned>(currentCodeConst->source) + currentCodeConst->arrayCount > static_cast<unsigned>(sourceIndexToFind))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << currentCodeConst->name << '[' << (static_cast<unsigned>(sourceIndexToFind) - static_cast<unsigned>(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<MaterialConstantSource>(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<MaterialTextureSource>(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<AssetVertexShader>(&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<size_t>(pass.perPrimArgCount) + static_cast<size_t>(pass.perObjArgCount) + static_cast<size_t>(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<AssetPixelShader>(&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<size_t>(pass.perPrimArgCount) + static_cast<size_t>(pass.perObjArgCount) + static_cast<size_t>(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<size_t>(dst);
|
||||
assert(dstIndex < std::extent_v<decltype(materialStreamDestinationNames)>);
|
||||
if (dstIndex < std::extent_v<decltype(materialStreamDestinationNames)>)
|
||||
return materialStreamDestinationNames[dstIndex];
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* GetStreamSourceString(const MaterialStreamStreamSource_e src)
|
||||
{
|
||||
const auto srcIndex = static_cast<size_t>(src);
|
||||
assert(srcIndex < std::extent_v<decltype(materialStreamSourceNames)>);
|
||||
if (srcIndex < std::extent_v<decltype(materialStreamSourceNames)>)
|
||||
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<AssetVertexDecl>(&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<size_t>(vertexDecl->streamCount), std::extent_v<decltype(MaterialVertexStreamRouting::data)>);
|
||||
for (auto streamIndex = 0u; streamIndex < streamCount; streamIndex++)
|
||||
{
|
||||
const auto& stream = vertexDecl->routing.data[streamIndex];
|
||||
Indent();
|
||||
m_stream << "vertex." << GetStreamDestinationString(static_cast<MaterialStreamDestination_e>(stream.dest)) << " = code."
|
||||
<< GetStreamSourceString(static_cast<MaterialStreamStreamSource_e>(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<std::string> techniqueNames(std::extent_v<decltype(techniqueTypeNames)>);
|
||||
|
||||
for (auto techniqueIndex = 0u; techniqueIndex < std::extent_v<decltype(techniqueTypeNames)>; 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<decltype(techniqueTypeNames)>);
|
||||
const auto commonTechset = ConvertToCommonTechset(techset);
|
||||
|
||||
techset::DumpCommonTechset(commonNames, context, commonTechset);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace techset
|
||||
{
|
||||
void DumperIW4::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetTechniqueSet::Type>& asset)
|
||||
{
|
||||
const auto* techniqueSet = asset.Asset();
|
||||
DumpTechset(context, *techniqueSet);
|
||||
|
||||
auto* techniqueState = context.GetZoneAssetDumperState<TechniqueDumpingZoneState>();
|
||||
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
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/IW4/IW4.h"
|
||||
|
||||
namespace techset
|
||||
{
|
||||
class DumperIW4 final : public AbstractAssetDumper<IW4::AssetTechniqueSet>
|
||||
{
|
||||
protected:
|
||||
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW4::AssetTechniqueSet::Type>& asset) override;
|
||||
};
|
||||
} // namespace techset
|
||||
@@ -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"
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/T6/T6.h"
|
||||
|
||||
namespace techset
|
||||
{
|
||||
class DumperT6 final : public AbstractAssetDumper<T6::AssetTechniqueSet>
|
||||
{
|
||||
public:
|
||||
explicit DumperT6(bool debug);
|
||||
|
||||
void Dump(AssetDumpingContext& context) override;
|
||||
|
||||
protected:
|
||||
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<T6::AssetTechniqueSet::Type>& asset) override;
|
||||
|
||||
private:
|
||||
bool m_debug;
|
||||
};
|
||||
} // namespace techset
|
||||
@@ -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;
|
||||
|
||||
46
src/ObjWriting/Techset/PixelShaderDumper.cpp.template
Normal file
46
src/ObjWriting/Techset/PixelShaderDumper.cpp.template
Normal file
@@ -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 <type_traits>
|
||||
|
||||
using namespace GAME;
|
||||
|
||||
#set CLASS_NAME "PixelShaderDumper" + GAME
|
||||
|
||||
namespace techset
|
||||
{
|
||||
void CLASS_NAME::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetPixelShader::Type>& asset)
|
||||
{
|
||||
const auto& shader = *asset.Asset();
|
||||
const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(shader.name));
|
||||
|
||||
if (!shaderFile)
|
||||
return;
|
||||
|
||||
shaderFile->write(reinterpret_cast<const char*>(shader.prog.loadDef.program),
|
||||
static_cast<std::streamsize>(shader.prog.loadDef.programSize)
|
||||
* sizeof(std::remove_pointer_t<decltype(GfxPixelShaderLoadDef::program)>));
|
||||
}
|
||||
} // namespace techset
|
||||
25
src/ObjWriting/Techset/PixelShaderDumper.h.template
Normal file
25
src/ObjWriting/Techset/PixelShaderDumper.h.template
Normal file
@@ -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<GAME::AssetPixelShader>
|
||||
{
|
||||
protected:
|
||||
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<GAME::AssetPixelShader::Type>& asset) override;
|
||||
};
|
||||
} // namespace techset
|
||||
@@ -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 <cassert>
|
||||
#include <format>
|
||||
|
||||
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<const char*>(pixelShader.prog.loadDef.program),
|
||||
static_cast<std::streamsize>(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<const char*>(vertexShader.prog.loadDef.program),
|
||||
static_cast<std::streamsize>(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<techset::CommonStreamRouting> commonRouting;
|
||||
|
||||
#if defined(FEATURE_IW4)
|
||||
if (vertexDecl && vertexDecl->name && vertexDecl->name[0] != ',')
|
||||
#else
|
||||
if (vertexDecl)
|
||||
#endif
|
||||
{
|
||||
const auto streamCount = std::min(static_cast<size_t>(vertexDecl->streamCount), std::extent_v<decltype(MaterialVertexStreamRouting::data)>);
|
||||
for (auto streamIndex = 0u; streamIndex < streamCount; streamIndex++)
|
||||
@@ -70,12 +121,24 @@ namespace
|
||||
static_cast<techset::CommonStreamDestination>(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<techset::CommonCodeSamplerSource>(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<decltype(GfxVertexShaderLoadDef::program)>),
|
||||
#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<decltype(GfxPixelShaderLoadDef::program)>),
|
||||
#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<unsigned>(pass.materialType), static_cast<unsigned>(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<MaterialConstantZoneState>()->EnsureInitialized();
|
||||
AbstractAssetDumper::Dump(context);
|
||||
}
|
||||
|
||||
void DumperT6::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetTechniqueSet::Type>& asset)
|
||||
void CLASS_NAME::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetTechniqueSet::Type>& asset)
|
||||
{
|
||||
const auto* techniqueSet = asset.Asset();
|
||||
DumpTechset(context, *techniqueSet);
|
||||
DumpTechniques(context, *techniqueSet, m_debug);
|
||||
#if defined(DUMP_SHADERS)
|
||||
DumpShaders(context, *techniqueSet);
|
||||
#endif
|
||||
}
|
||||
} // namespace techset
|
||||
33
src/ObjWriting/Techset/TechsetDumper.h.template
Normal file
33
src/ObjWriting/Techset/TechsetDumper.h.template
Normal file
@@ -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<GAME::AssetTechniqueSet>
|
||||
{
|
||||
public:
|
||||
explicit CLASS_NAME(bool debug);
|
||||
|
||||
void Dump(AssetDumpingContext& context) override;
|
||||
|
||||
protected:
|
||||
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<GAME::AssetTechniqueSet::Type>& asset) override;
|
||||
|
||||
private:
|
||||
bool m_debug;
|
||||
};
|
||||
} // namespace techset
|
||||
46
src/ObjWriting/Techset/VertexShaderDumper.cpp.template
Normal file
46
src/ObjWriting/Techset/VertexShaderDumper.cpp.template
Normal file
@@ -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 <type_traits>
|
||||
|
||||
using namespace GAME;
|
||||
|
||||
#set CLASS_NAME "VertexShaderDumper" + GAME
|
||||
|
||||
namespace techset
|
||||
{
|
||||
void CLASS_NAME::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetVertexShader::Type>& asset)
|
||||
{
|
||||
const auto& shader = *asset.Asset();
|
||||
const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(shader.name));
|
||||
|
||||
if (!shaderFile)
|
||||
return;
|
||||
|
||||
shaderFile->write(reinterpret_cast<const char*>(shader.prog.loadDef.program),
|
||||
static_cast<std::streamsize>(shader.prog.loadDef.programSize)
|
||||
* sizeof(std::remove_pointer_t<decltype(GfxVertexShaderLoadDef::program)>));
|
||||
}
|
||||
} // namespace techset
|
||||
25
src/ObjWriting/Techset/VertexShaderDumper.h.template
Normal file
25
src/ObjWriting/Techset/VertexShaderDumper.h.template
Normal file
@@ -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<GAME::AssetVertexShader>
|
||||
{
|
||||
protected:
|
||||
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<GAME::AssetVertexShader::Type>& asset) override;
|
||||
};
|
||||
} // namespace techset
|
||||
Reference in New Issue
Block a user