mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-03-26 06:23:03 +00:00
feat: template techset and shader dumping for IW4,T6
This commit is contained in:
426
src/ObjWriting/Techset/TechsetDumper.cpp.template
Normal file
426
src/ObjWriting/Techset/TechsetDumper.cpp.template
Normal file
@@ -0,0 +1,426 @@
|
||||
#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 "Techset/CommonTechniqueDumper.h"
|
||||
#include "Techset/CommonTechsetDumper.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 GAME;
|
||||
|
||||
namespace
|
||||
{
|
||||
#if defined(DUMP_SHADERS)
|
||||
void DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader& pixelShader)
|
||||
{
|
||||
const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(pixelShader.name));
|
||||
|
||||
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)
|
||||
{
|
||||
const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(vertexShader.name));
|
||||
|
||||
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)
|
||||
{
|
||||
auto* shaderState = context.GetZoneAssetDumperState<techset::ShaderDumpingZoneState>();
|
||||
|
||||
for (const auto* technique : techset.techniques)
|
||||
{
|
||||
if (!technique || !shaderState->ShouldDumpTechnique(technique))
|
||||
continue;
|
||||
|
||||
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
|
||||
{
|
||||
const auto* pixelShader = technique->passArray[passIndex].pixelShader;
|
||||
if (pixelShader && shaderState->ShouldDumpPixelShader(pixelShader))
|
||||
DumpPixelShader(context, *pixelShader);
|
||||
|
||||
const auto* vertexShader = technique->passArray[passIndex].vertexShader;
|
||||
if (vertexShader && shaderState->ShouldDumpVertexShader(vertexShader))
|
||||
DumpVertexShader(context, *vertexShader);
|
||||
}
|
||||
}
|
||||
}
|
||||
#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++)
|
||||
{
|
||||
const auto& routing = vertexDecl->routing.data[streamIndex];
|
||||
commonRouting.emplace_back(static_cast<techset::CommonStreamSource>(routing.source),
|
||||
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:
|
||||
case MTL_ARG_CODE_PIXEL_CONST:
|
||||
{
|
||||
const techset::CommonShaderArgCodeConstValue codeConstValue{
|
||||
.m_index = static_cast<techset::CommonCodeConstSource>(arg.u.codeConst.index),
|
||||
.m_first_row = arg.u.codeConst.firstRow,
|
||||
.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,
|
||||
};
|
||||
const techset::CommonShaderArgDestination destination = {
|
||||
.dx11 = {
|
||||
.m_location = location,
|
||||
.m_size = arg.size,
|
||||
.m_buffer = arg.buffer,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value);
|
||||
}
|
||||
|
||||
case MTL_ARG_MATERIAL_VERTEX_CONST:
|
||||
case MTL_ARG_MATERIAL_PIXEL_CONST:
|
||||
{
|
||||
const techset::CommonShaderArgValue value{
|
||||
.name_hash = arg.u.nameHash,
|
||||
};
|
||||
#if defined(IS_DX11)
|
||||
const techset::CommonShaderArgLocationDx11 location{
|
||||
.constant_buffer_offset = arg.location.offset,
|
||||
};
|
||||
const techset::CommonShaderArgDestination destination{
|
||||
.dx11 = {
|
||||
.m_location = location,
|
||||
.m_size = arg.size,
|
||||
.m_buffer = arg.buffer,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value);
|
||||
}
|
||||
|
||||
case MTL_ARG_CODE_PIXEL_SAMPLER:
|
||||
{
|
||||
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,
|
||||
};
|
||||
const techset::CommonShaderArgDestination destination = {
|
||||
.dx11 = {
|
||||
.m_location = location,
|
||||
.m_size = arg.size,
|
||||
.m_buffer = arg.buffer,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value);
|
||||
}
|
||||
|
||||
case MTL_ARG_MATERIAL_PIXEL_SAMPLER:
|
||||
{
|
||||
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,
|
||||
};
|
||||
const techset::CommonShaderArgDestination destination = {
|
||||
.dx11 = {
|
||||
.m_location = location,
|
||||
.m_size = arg.size,
|
||||
.m_buffer = arg.buffer,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value);
|
||||
}
|
||||
|
||||
default:
|
||||
case MTL_ARG_LITERAL_VERTEX_CONST:
|
||||
case MTL_ARG_LITERAL_PIXEL_CONST:
|
||||
{
|
||||
techset::CommonShaderArgValue value{};
|
||||
if (arg.u.literalConst)
|
||||
{
|
||||
value.literal_value = {
|
||||
(*arg.u.literalConst)[0],
|
||||
(*arg.u.literalConst)[1],
|
||||
(*arg.u.literalConst)[2],
|
||||
(*arg.u.literalConst)[3],
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(IS_DX11)
|
||||
const techset::CommonShaderArgLocationDx11 location{
|
||||
.constant_buffer_offset = arg.location.offset,
|
||||
};
|
||||
const techset::CommonShaderArgDestination destination = {
|
||||
.dx11 = {
|
||||
.m_location = location,
|
||||
.m_size = arg.size,
|
||||
.m_buffer = arg.buffer,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
techset::CommonTechniqueShader ConvertToCommonShader(const MaterialVertexShader* vertexShader)
|
||||
{
|
||||
techset::CommonTechniqueShader result(techset::CommonTechniqueShaderType::VERTEX, std::string());
|
||||
if (!vertexShader)
|
||||
return result;
|
||||
|
||||
if (vertexShader->name)
|
||||
result.m_name = vertexShader->name;
|
||||
|
||||
if (vertexShader->prog.loadDef.program)
|
||||
{
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
techset::CommonTechniqueShader ConvertToCommonShader(const MaterialPixelShader* pixelShader)
|
||||
{
|
||||
techset::CommonTechniqueShader result(techset::CommonTechniqueShaderType::PIXEL, std::string());
|
||||
if (!pixelShader)
|
||||
return result;
|
||||
|
||||
if (pixelShader->name)
|
||||
result.m_name = pixelShader->name;
|
||||
|
||||
if (pixelShader->prog.loadDef.program)
|
||||
{
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
techset::CommonTechnique ConvertToCommonTechnique(const MaterialTechnique& technique, const bool debug)
|
||||
{
|
||||
techset::CommonTechnique commonTechnique(technique.name ? technique.name : std::string(), technique.flags);
|
||||
|
||||
for (auto passIndex = 0u; passIndex < technique.passCount; passIndex++)
|
||||
{
|
||||
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
|
||||
"passthrough",
|
||||
ConvertToCommonShader(pass.vertexShader),
|
||||
ConvertToCommonShader(pass.pixelShader),
|
||||
ConvertToCommonVertexDeclaration(pass.vertexDecl),
|
||||
std::move(comment));
|
||||
|
||||
if (pass.args)
|
||||
{
|
||||
const size_t totalArgCount = pass.perPrimArgCount + pass.perObjArgCount + pass.stableArgCount;
|
||||
commonPass.m_args.reserve(totalArgCount);
|
||||
for (auto argIndex = 0uz; argIndex < totalArgCount; argIndex++)
|
||||
commonPass.m_args.emplace_back(ConvertToCommonArg(pass.args[argIndex]));
|
||||
}
|
||||
|
||||
commonTechnique.m_passes.emplace_back(std::move(commonPass));
|
||||
}
|
||||
|
||||
return commonTechnique;
|
||||
}
|
||||
|
||||
void DumpTechniques(AssetDumpingContext& context, const MaterialTechniqueSet& techset, const bool debug)
|
||||
{
|
||||
auto* techniqueState = context.GetZoneAssetDumperState<techset::TechniqueDumpingZoneState>();
|
||||
const auto* materialConstantState = context.GetZoneAssetDumperState<MaterialConstantZoneState>();
|
||||
for (const auto* technique : techset.techniques)
|
||||
{
|
||||
if (technique && techniqueState->ShouldDumpTechnique(technique))
|
||||
{
|
||||
const auto commonTechnique = ConvertToCommonTechnique(*technique, debug);
|
||||
|
||||
techset::DumpCommonTechnique(context,
|
||||
commonTechnique,
|
||||
#if defined(IS_DX9)
|
||||
techset::DxVersion::DX9,
|
||||
#elif defined(IS_DX11)
|
||||
techset::DxVersion::DX11,
|
||||
#endif
|
||||
commonCodeSourceInfos,
|
||||
commonRoutingInfos,
|
||||
*materialConstantState,
|
||||
debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const auto commonTechset = ConvertToCommonTechset(techset);
|
||||
|
||||
techset::DumpCommonTechset(commonTechniqueTypeNames, context, commonTechset);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#set CLASS_NAME "Dumper" + GAME
|
||||
|
||||
namespace techset
|
||||
{
|
||||
CLASS_NAME::CLASS_NAME(const bool debug)
|
||||
: m_debug(debug)
|
||||
{
|
||||
}
|
||||
|
||||
void CLASS_NAME::Dump(AssetDumpingContext& context)
|
||||
{
|
||||
context.GetZoneAssetDumperState<MaterialConstantZoneState>()->EnsureInitialized();
|
||||
AbstractAssetDumper::Dump(context);
|
||||
}
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user