2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-11-24 05:32:06 +00:00

feat: dump material techniques for T6

This commit is contained in:
Jan Laupetin
2025-11-13 22:44:09 +00:00
parent 4e43f32f14
commit 466d7ab0f2
8 changed files with 221 additions and 36 deletions

View File

@@ -32,14 +32,17 @@ namespace d3d11
m_flags(0u) m_flags(0u)
{ {
} }
} // namespace d3d11
static constexpr auto TAG_RDEF = FileUtils::MakeMagic32('R', 'D', 'E', 'F'); namespace
static constexpr auto TAG_SHDR = FileUtils::MakeMagic32('S', 'H', 'D', 'R'); {
constexpr auto TAG_RDEF = FileUtils::MakeMagic32('R', 'D', 'E', 'F');
constexpr auto TAG_SHDR = FileUtils::MakeMagic32('S', 'H', 'D', 'R');
static constexpr auto VERSION_5_0 = 0x500; constexpr auto VERSION_5_0 = 0x500;
static constexpr auto VERSION_5_1 = 0x501; constexpr auto VERSION_5_1 = 0x501;
static constexpr auto TARGET_VERSION_MASK = 0xFFFF; constexpr auto TARGET_VERSION_MASK = 0xFFFF;
static constexpr auto CHUNK_TABLE_OFFSET = 28u; constexpr auto CHUNK_TABLE_OFFSET = 28u;
struct FileRdefHeader struct FileRdefHeader
{ {
@@ -669,16 +672,16 @@ namespace d3d11
return true; return true;
} }
} // namespace d3d11 } // namespace
std::unique_ptr<ShaderInfo> ShaderAnalyser::GetShaderInfo(const uint8_t* shader, const size_t shaderSize) std::unique_ptr<ShaderInfo> ShaderAnalyser::GetShaderInfo(const void* shader, const size_t shaderSize)
{ {
if (shader == nullptr || shaderSize == 0) if (shader == nullptr || shaderSize == 0)
return nullptr; return nullptr;
auto shaderInfo = std::make_unique<ShaderInfo>(); auto shaderInfo = std::make_unique<ShaderInfo>();
if (!PopulateShaderInfoFromBytes(*shaderInfo, shader, shaderSize)) if (!PopulateShaderInfoFromBytes(*shaderInfo, static_cast<const uint8_t*>(shader), shaderSize))
return nullptr; return nullptr;
return shaderInfo; return shaderInfo;

View File

@@ -1,12 +1,13 @@
#pragma once #pragma once
#include <cstdint>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
namespace d3d11 namespace d3d11
{ {
enum class ShaderType enum class ShaderType : std::uint8_t
{ {
UNKNOWN, UNKNOWN,
PIXEL_SHADER, PIXEL_SHADER,
@@ -33,7 +34,7 @@ namespace d3d11
unsigned m_flags; unsigned m_flags;
}; };
enum class ConstantBufferType enum class ConstantBufferType : std::uint8_t
{ {
UNKNOWN, UNKNOWN,
CBUFFER, CBUFFER,
@@ -59,7 +60,7 @@ namespace d3d11
std::vector<ConstantBufferVariable> m_variables; std::vector<ConstantBufferVariable> m_variables;
}; };
enum class BoundResourceType enum class BoundResourceType : std::uint8_t
{ {
UNKNOWN, UNKNOWN,
CBUFFER, CBUFFER,
@@ -68,7 +69,7 @@ namespace d3d11
SAMPLER SAMPLER
}; };
enum class BoundResourceReturnType enum class BoundResourceReturnType : std::uint8_t
{ {
UNKNOWN, UNKNOWN,
UNORM, UNORM,
@@ -81,7 +82,7 @@ namespace d3d11
CONTINUED, CONTINUED,
}; };
enum class BoundResourceDimension enum class BoundResourceDimension : std::uint8_t
{ {
UNKNOWN, UNKNOWN,
BUFFER, BUFFER,
@@ -131,6 +132,6 @@ namespace d3d11
class ShaderAnalyser class ShaderAnalyser
{ {
public: public:
static std::unique_ptr<ShaderInfo> GetShaderInfo(const uint8_t* shader, size_t shaderSize); static std::unique_ptr<ShaderInfo> GetShaderInfo(const void* shader, size_t shaderSize);
}; };
} // namespace d3d11 } // namespace d3d11

View File

@@ -1,12 +1,13 @@
#pragma once #pragma once
#include <cstdint>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
namespace d3d9 namespace d3d9
{ {
enum class ShaderType enum class ShaderType : std::uint8_t
{ {
UNKNOWN, UNKNOWN,
PIXEL_SHADER, PIXEL_SHADER,
@@ -14,7 +15,7 @@ namespace d3d9
}; };
// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxregister-set // https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxregister-set
enum class RegisterSet enum class RegisterSet : std::uint8_t
{ {
BOOL, BOOL,
INT_4, INT_4,
@@ -26,7 +27,7 @@ namespace d3d9
}; };
// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxparameter-class // https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxparameter-class
enum class ParameterClass enum class ParameterClass : std::uint8_t
{ {
SCALAR, SCALAR,
VECTOR, VECTOR,
@@ -40,7 +41,7 @@ namespace d3d9
}; };
// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxparameter-type // https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxparameter-type
enum class ParameterType enum class ParameterType : std::uint8_t
{ {
VOID, VOID,
BOOL, BOOL,

View File

@@ -10,15 +10,21 @@ namespace techset
{ {
public: public:
std::string m_name; std::string m_name;
uint32_t m_version_major; const void* m_shader_bin;
uint32_t m_version_minor; size_t m_shader_bin_size;
};
enum class DxVersion : std::uint8_t
{
DX9,
DX11
}; };
class CommonPass class CommonPass
{ {
public: public:
uint64_t m_flags;
uint32_t m_sampler_flags; uint32_t m_sampler_flags;
DxVersion m_dx_version;
CommonTechniqueShader m_vertex_shader; CommonTechniqueShader m_vertex_shader;
CommonTechniqueShader m_pixel_shader; CommonTechniqueShader m_pixel_shader;
}; };
@@ -26,6 +32,7 @@ namespace techset
class CommonTechnique class CommonTechnique
{ {
public: public:
std::string m_name;
uint64_t m_flags; uint64_t m_flags;
std::vector<CommonPass> m_passes; std::vector<CommonPass> m_passes;
}; };

View File

@@ -6,7 +6,6 @@
#include "Techset/CommonTechsetDumper.h" #include "Techset/CommonTechsetDumper.h"
#include "Techset/TechniqueDumpingZoneState.h" #include "Techset/TechniqueDumpingZoneState.h"
#include <sstream>
#include <unordered_set> #include <unordered_set>
using namespace T6; using namespace T6;
@@ -102,18 +101,51 @@ namespace
techset::CommonTechnique ConvertToCommonTechnique(const MaterialTechnique& technique) techset::CommonTechnique ConvertToCommonTechnique(const MaterialTechnique& technique)
{ {
std::vector<std::string> techniqueNames(std::extent_v<decltype(techniqueTypeNames)>); std::vector<techset::CommonPass> passes;
for (auto techniqueIndex = 0u; techniqueIndex < std::extent_v<decltype(techniqueTypeNames)>; techniqueIndex++) for (auto passIndex = 0u; passIndex < technique.passCount; passIndex++)
{ {
const auto* technique = techset.techniques[techniqueIndex]; const auto& pass = technique.passArray[passIndex];
if (technique && technique->name)
techniqueNames[techniqueIndex] = technique->name; techset::CommonTechniqueShader vertexShader{};
techset::CommonTechniqueShader pixelShader{};
if (pass.vertexShader)
{
if (pass.vertexShader->name)
vertexShader.m_name = pass.vertexShader->name;
if (pass.vertexShader->prog.loadDef.program)
{
vertexShader.m_shader_bin = pass.vertexShader->prog.loadDef.program;
vertexShader.m_shader_bin_size = pass.vertexShader->prog.loadDef.programSize * sizeof(uint32_t);
}
}
if (pass.pixelShader)
{
if (pass.pixelShader->name)
pixelShader.m_name = pass.pixelShader->name;
if (pass.pixelShader->prog.loadDef.program)
{
pixelShader.m_shader_bin = pass.pixelShader->prog.loadDef.program;
pixelShader.m_shader_bin_size = pass.pixelShader->prog.loadDef.programSize * sizeof(uint32_t);
}
}
passes.emplace_back(techset::CommonPass{
.m_sampler_flags = pass.customSamplerFlags,
.m_dx_version = techset::DxVersion::DX11,
.m_vertex_shader = vertexShader,
.m_pixel_shader = pixelShader,
});
} }
return techset::CommonTechset{ return techset::CommonTechnique{
.m_name = techset.name, .m_name = technique.name ? technique.name : std::string(),
.m_technique_names = std::move(techniqueNames), .m_flags = technique.flags,
.m_passes = std::move(passes),
}; };
} }

View File

@@ -0,0 +1,143 @@
#include "CommonTechniqueDumper.h"
#include "Dumping/AbstractTextDumper.h"
#include "Shader/D3D11ShaderAnalyser.h"
#include "Shader/D3D9ShaderAnalyser.h"
#include "Techset/TechsetCommon.h"
#include <cassert>
#include <cstdint>
using namespace techset;
namespace
{
enum class TechniqueShaderType : std::uint8_t
{
VERTEX_SHADER,
PIXEL_SHADER
};
class TechniqueFileWriter : public AbstractTextDumper
{
public:
explicit TechniqueFileWriter(std::ostream& stream)
: AbstractTextDumper(stream)
{
}
void DumpTechnique(const CommonTechnique& technique)
{
#ifdef TECHSET_DEBUG
if (technique.m_flags)
{
for (auto i = 0u; i < sizeof(CommonTechnique::m_flags) * 8u; i++)
{
const auto mask = 1ui64 << i;
if (technique.m_flags & mask)
{
Indent();
m_stream << std::format("// TECHNIQUE FLAGS: 0x{:x}\n", mask);
}
}
}
#endif
for (const auto& pass : technique.m_passes)
DumpPass(pass);
}
private:
void DumpPass(const CommonPass& pass)
{
m_stream << "{\n";
IncIndent();
#ifdef TECHSET_DEBUG
for (auto i = 0u; i < sizeof(CommonPass::m_sampler_flags) * 8u; i++)
{
const auto mask = 1ui64 << i;
if (pass.m_sampler_flags & mask)
{
Indent();
m_stream << std::format("// CUSTOM SAMPLER FLAGS: 0x{:x}\n", mask);
}
}
#endif
DumpStateMap();
DumpShader(pass, pass.m_vertex_shader, TechniqueShaderType::VERTEX_SHADER);
DumpShader(pass, pass.m_pixel_shader, TechniqueShaderType::PIXEL_SHADER);
// DumpVertexDecl(pass);
DecIndent();
m_stream << "}\n";
}
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";
}
void DumpShader(const CommonPass& pass, const CommonTechniqueShader& shader, const TechniqueShaderType shaderType) const
{
if (!shader.m_shader_bin)
{
if (!shader.m_name.empty())
m_stream << std::format("// Cannot dump shader {} as its data is not loaded\n", shader.m_name);
return;
}
unsigned versionMajor, versionMinor;
if (pass.m_dx_version == DxVersion::DX9)
{
const auto shaderInfo = d3d9::ShaderAnalyser::GetShaderInfo(shader.m_shader_bin, shader.m_shader_bin_size);
assert(shaderInfo);
if (!shaderInfo)
return;
versionMajor = shaderInfo->m_version_major;
versionMinor = shaderInfo->m_version_minor;
}
else
{
assert(pass.m_dx_version == DxVersion::DX11);
const auto shaderInfo = d3d11::ShaderAnalyser::GetShaderInfo(shader.m_shader_bin, shader.m_shader_bin_size);
assert(shaderInfo);
if (!shaderInfo)
return;
versionMajor = shaderInfo->m_version_major;
versionMinor = shaderInfo->m_version_minor;
}
const auto shaderTypeName = shaderType == TechniqueShaderType::VERTEX_SHADER ? "vertexShader" : "pixelShader";
m_stream << "\n";
Indent();
m_stream << std::format("{} {}.{} \"{}\"\n", shaderTypeName, versionMajor, versionMinor, shader.m_name);
Indent();
m_stream << "{\n";
Indent();
m_stream << "}\n";
}
};
} // namespace
namespace techset
{
void DumpCommonTechnique(const AssetDumpingContext& context, const CommonTechnique& technique)
{
const auto techniqueFile = context.OpenAssetFile(GetFileNameForTechniqueName(technique.m_name));
if (techniqueFile)
{
TechniqueFileWriter writer(*techniqueFile);
writer.DumpTechnique(technique);
}
}
} // namespace techset

View File

@@ -1,9 +1,9 @@
#pragma once #pragma once
#include "Dumping/AssetDumpingContext.h" #include "Dumping/AssetDumpingContext.h"
#include "Techset/CommonTechset.h" #include "Techset/CommonTechnique.h"
namespace techset namespace techset
{ {
void DumpCommonTechnique(const AssetDumpingContext& context, const CommonTechset& techset); void DumpCommonTechnique(const AssetDumpingContext& context, const CommonTechnique& technique);
} // namespace techset } // namespace techset

View File

@@ -1,7 +1,6 @@
#include "CommonTechsetDumper.h" #include "CommonTechsetDumper.h"
#include "Dumping/AbstractTextDumper.h" #include "Dumping/AbstractTextDumper.h"
#include "Game/IW3/Material/MaterialConstantZoneStateIW3.h"
#include "Techset/TechsetCommon.h" #include "Techset/TechsetCommon.h"
#include <cassert> #include <cassert>
@@ -36,8 +35,7 @@ namespace
dumpedTechniques[techniqueIndex] = true; dumpedTechniques[techniqueIndex] = true;
WriteTechniqueType(techniqueIndex); WriteTechniqueType(techniqueIndex);
for (auto nextTechniqueIndex = techniqueIndex + 1; nextTechniqueIndex < std::extent_v<decltype(IW3::MaterialTechniqueSet::techniques)>; for (auto nextTechniqueIndex = techniqueIndex + 1; nextTechniqueIndex < techniqueCount; nextTechniqueIndex++)
nextTechniqueIndex++)
{ {
if (techset.m_technique_names[nextTechniqueIndex] != technique) if (techset.m_technique_names[nextTechniqueIndex] != technique)
continue; continue;