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

feat: dump t6 shader args

This commit is contained in:
Jan Laupetin
2025-11-16 00:12:52 +00:00
parent a064b5fd71
commit 38960a25f3
21 changed files with 2341 additions and 71 deletions

View File

@@ -5862,8 +5862,8 @@ namespace T6
struct
{
char textureIndex;
char samplerIndex;
uint8_t textureIndex;
uint8_t samplerIndex;
};
};
@@ -5948,7 +5948,6 @@ namespace T6
CONST_SRC_CODE_DEPTH_FROM_CLIP = 0x42,
CONST_SRC_CODE_CODE_MESH_ARG_0 = 0x43,
CONST_SRC_CODE_CODE_MESH_ARG_1 = 0x44,
CONST_SRC_CODE_CODE_MESH_ARG_LAST = 0x44,
CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS = 0x45,
CONST_SRC_CODE_GRID_LIGHTING_SH_0 = 0x46,
CONST_SRC_CODE_GRID_LIGHTING_SH_1 = 0x47,
@@ -6133,6 +6132,67 @@ namespace T6
CONST_SRC_NONE,
};
enum MaterialTextureSource
{
TEXTURE_SRC_CODE_BLACK = 0x0,
TEXTURE_SRC_CODE_WHITE = 0x1,
TEXTURE_SRC_CODE_IDENTITY_NORMAL_MAP = 0x2,
TEXTURE_SRC_CODE_MODEL_LIGHTING = 0x3,
TEXTURE_SRC_CODE_LIGHTMAP_PRIMARY = 0x4,
TEXTURE_SRC_CODE_LIGHTMAP_SECONDARY = 0x5,
TEXTURE_SRC_CODE_SHADOWMAP_SUN = 0x6,
TEXTURE_SRC_CODE_SHADOWMAP_SPOT = 0x7,
TEXTURE_SRC_CODE_FEEDBACK = 0x8,
TEXTURE_SRC_CODE_RESOLVED_POST_SUN = 0x9,
TEXTURE_SRC_CODE_RESOLVED_SCENE = 0xA,
TEXTURE_SRC_CODE_POST_EFFECT_SRC = 0xB,
TEXTURE_SRC_CODE_POST_EFFECT_GODRAYS = 0xC,
TEXTURE_SRC_CODE_POST_EFFECT_0 = 0xD,
TEXTURE_SRC_CODE_POST_EFFECT_1 = 0xE,
TEXTURE_SRC_CODE_LIGHT_ATTENUATION = 0xF,
TEXTURE_SRC_CODE_DLIGHT_ATTENUATION = 0x10,
TEXTURE_SRC_CODE_OUTDOOR = 0x11,
TEXTURE_SRC_CODE_FLOATZ = 0x12,
TEXTURE_SRC_CODE_PROCESSED_FLOATZ = 0x13,
TEXTURE_SRC_CODE_RAW_FLOATZ = 0x14,
TEXTURE_SRC_CODE_STENCIL = 0x15,
TEXTURE_SRC_CODE_CINEMATIC_Y = 0x16,
TEXTURE_SRC_CODE_CINEMATIC_CR = 0x17,
TEXTURE_SRC_CODE_CINEMATIC_CB = 0x18,
TEXTURE_SRC_CODE_CINEMATIC_A = 0x19,
TEXTURE_SRC_CODE_REFLECTION_PROBE = 0x1A,
TEXTURE_SRC_CODE_FEATHER_FLOAT_Z = 0x1B,
TEXTURE_SRC_CODE_TEXTURE_0 = 0x1C,
TEXTURE_SRC_CODE_TEXTURE_1 = 0x1D,
TEXTURE_SRC_CODE_TEXTURE_2 = 0x1E,
TEXTURE_SRC_CODE_TEXTURE_3 = 0x1F,
TEXTURE_SRC_CODE_IMPACT_MASK_DEPRECATED = 0x20,
TEXTURE_SRC_CODE_UI3D = 0x21,
TEXTURE_SRC_CODE_MISSILE_CAM = 0x22,
TEXTURE_SRC_CODE_MISSILE_CAM_0 = 0x23,
TEXTURE_SRC_CODE_MISSILE_CAM_1 = 0x24,
TEXTURE_SRC_CODE_MISSILE_CAM_2 = 0x25,
TEXTURE_SRC_CODE_MISSILE_CAM_3 = 0x26,
TEXTURE_SRC_CODE_COMPOSITE_RESULT = 0x27,
TEXTURE_SRC_CODE_HEATMAP = 0x28,
TEXTURE_SRC_CODE_SONAR_COLOR = 0x29,
TEXTURE_SRC_CODE_SONAR_DEPTH = 0x2A,
TEXTURE_SRC_CODE_QRCODE_0 = 0x2B,
TEXTURE_SRC_CODE_QRCODE_1 = 0x2C,
TEXTURE_SRC_CODE_QRCODE_2 = 0x2D,
TEXTURE_SRC_CODE_QRCODE_3 = 0x2E,
TEXTURE_SRC_CODE_QRCODE_4 = 0x2F,
TEXTURE_SRC_CODE_QRCODE_5 = 0x30,
TEXTURE_SRC_CODE_QRCODE_6 = 0x31,
TEXTURE_SRC_CODE_QRCODE_7 = 0x32,
TEXTURE_SRC_CODE_QRCODE_8 = 0x33,
TEXTURE_SRC_CODE_QRCODE_9 = 0x34,
TEXTURE_SRC_CODE_QRCODE_10 = 0x35,
TEXTURE_SRC_CODE_QRCODE_11 = 0x36,
TEXTURE_SRC_CODE_COUNT
};
struct CodeConstantSource
{
const char* name;

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,60 @@
#include "CommonTechnique.h"
#include <algorithm>
namespace techset
{
CommonCodeSourceInfos::CommonCodeSourceInfos(const CommonCodeConstSourceInfo* codeConstSourceInfos,
const size_t codeConstCount,
const CommonCodeSamplerSourceInfo* codeSamplerSourceInfos,
const size_t codeSamplerCount)
: m_code_const_source_infos(codeConstCount),
m_code_sampler_source_infos(codeSamplerCount)
{
std::copy(codeConstSourceInfos, &codeConstSourceInfos[codeConstCount], m_code_const_source_infos.data());
std::ranges::sort(m_code_const_source_infos,
[](const CommonCodeConstSourceInfo& a, const CommonCodeConstSourceInfo& b) -> bool
{
return a.value < b.value;
});
std::copy(codeSamplerSourceInfos, &codeSamplerSourceInfos[codeSamplerCount], m_code_sampler_source_infos.data());
std::ranges::sort(m_code_sampler_source_infos,
[](const CommonCodeSamplerSourceInfo& a, const CommonCodeSamplerSourceInfo& b) -> bool
{
return a.value < b.value;
});
}
std::optional<CommonCodeConstSourceInfo> CommonCodeSourceInfos::GetInfoForCodeConstSource(const CommonCodeConstSource codeConstSource) const
{
for (const auto& codeConstSourceInfo : m_code_const_source_infos)
{
const auto codeConstSourceInfoEnd = static_cast<unsigned>(codeConstSourceInfo.value) + codeConstSourceInfo.arrayCount;
if (codeConstSourceInfo.value <= codeConstSource && codeConstSourceInfoEnd >= codeConstSource)
return codeConstSourceInfo;
if (codeConstSourceInfoEnd > codeConstSource)
return std::nullopt;
}
return std::nullopt;
}
std::optional<CommonCodeSamplerSourceInfo> CommonCodeSourceInfos::GetInfoForCodeSamplerSource(const CommonCodeSamplerSource codeSamplerSource) const
{
for (const auto& codeSamplerSourceInfo : m_code_sampler_source_infos)
{
if (codeSamplerSourceInfo.value == codeSamplerSource)
return codeSamplerSourceInfo;
if (codeSamplerSourceInfo.value > codeSamplerSource)
return std::nullopt;
}
return std::nullopt;
}
CommonStreamRoutingInfos::CommonStreamRoutingInfos(const CommonStreamRoutingSourceInfo* sourceInfos,
const size_t sourceCount,
const CommonStreamRoutingDestinationInfo* destinationNames,

View File

@@ -1,11 +1,19 @@
#pragma once
#include <array>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace techset
{
typedef std::uint8_t CommonStreamSource;
typedef std::uint8_t CommonStreamDestination;
typedef std::uint8_t CommonCodeConstSource;
typedef std::uint8_t CommonCodeSamplerSource;
struct CommonStreamRoutingSourceInfo
{
const char* name;
@@ -19,8 +27,44 @@ namespace techset
const char* abbreviation;
};
typedef std::uint8_t CommonStreamSource;
typedef std::uint8_t CommonStreamDestination;
enum class CommonCodeSourceUpdateFrequency : std::uint8_t
{
PER_PRIM,
PER_OBJECT,
RARELY,
CUSTOM,
};
struct CommonCodeConstSourceInfo
{
CommonCodeConstSource value;
const char* accessor;
std::uint8_t arrayCount;
CommonCodeSourceUpdateFrequency updateFrequency;
};
struct CommonCodeSamplerSourceInfo
{
CommonCodeSamplerSource value;
const char* accessor;
CommonCodeSourceUpdateFrequency updateFrequency;
};
class CommonCodeSourceInfos
{
public:
CommonCodeSourceInfos(const CommonCodeConstSourceInfo* codeConstSourceInfos,
size_t codeConstCount,
const CommonCodeSamplerSourceInfo* codeSamplerSourceInfos,
size_t codeSamplerCount);
[[nodiscard]] std::optional<CommonCodeConstSourceInfo> GetInfoForCodeConstSource(CommonCodeConstSource codeConstSource) const;
[[nodiscard]] std::optional<CommonCodeSamplerSourceInfo> GetInfoForCodeSamplerSource(CommonCodeSamplerSource codeSamplerSource) const;
private:
std::vector<CommonCodeConstSourceInfo> m_code_const_source_infos;
std::vector<CommonCodeSamplerSourceInfo> m_code_sampler_source_infos;
};
class CommonStreamRoutingInfos
{
@@ -41,6 +85,58 @@ namespace techset
std::vector<CommonStreamRoutingDestinationInfo> m_destinations;
};
union CommonShaderArgValue
{
std::array<float, 4> literal_value;
CommonCodeConstSource code_const_source;
CommonCodeSamplerSource code_sampler_source;
unsigned name_hash;
};
class CommonShaderArgDestinationDx9
{
public:
unsigned m_destination_register;
};
class CommonShaderArgDestinationDx11
{
public:
// In case of a constant: Offset in constant buffer
// In case of a sampler: Index of sampler
unsigned m_location;
unsigned m_size;
unsigned m_buffer;
};
union CommonShaderArgDestination
{
CommonShaderArgDestinationDx9 dx9;
CommonShaderArgDestinationDx11 dx11;
};
enum class CommonShaderArgType : std::uint8_t
{
// Value is set to a float4 value in the pass
LITERAL_CONST,
// Value is set to a float4 value in the material
MATERIAL_CONST,
// Value is set to a float4 value calculated in code
CODE_CONST,
// Value is set to a sampler from the material
MATERIAL_SAMPLER,
// Value is set to a sampler generated in code
CODE_SAMPLER
};
class CommonShaderArg
{
public:
CommonShaderArgType m_type;
CommonShaderArgDestination m_destination;
CommonShaderArgValue m_value;
};
class CommonStreamRouting
{
public:
@@ -60,6 +156,7 @@ namespace techset
std::string m_name;
const void* m_shader_bin;
size_t m_shader_bin_size;
std::vector<CommonShaderArg> m_args;
};
enum class DxVersion : std::uint8_t

View File

@@ -6,7 +6,7 @@
#include "ObjWriting.h"
#include "Zone/ZoneRegistry.h"
namespace IW3
namespace
{
const char* KNOWN_CONSTANT_NAMES[]{
"worldViewProjectionMatrix",
@@ -197,7 +197,10 @@ namespace IW3
"worldMap",
"worldMapSampler",
};
} // namespace
namespace IW3
{
void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{
for (const auto* zone : ZoneRegistry::GetRegistryForGame(GameId::IW3)->Zones())
@@ -219,7 +222,7 @@ namespace IW3
}
}
unsigned MaterialConstantZoneState::HashString(const std::string& str)
unsigned MaterialConstantZoneState::HashString(const std::string& str) const
{
return Common::R_HashString(str.c_str());
}

View File

@@ -13,6 +13,6 @@ namespace IW3
void ExtractNamesFromZoneInternal() override;
void ExtractNamesFromTechnique(const MaterialTechnique* technique);
void AddStaticKnownNames() override;
unsigned HashString(const std::string& str) override;
[[nodiscard]] unsigned HashString(const std::string& str) const override;
};
} // namespace IW3

View File

@@ -6,7 +6,7 @@
#include "ObjWriting.h"
#include "Zone/ZoneRegistry.h"
namespace IW4
namespace
{
const char* KNOWN_CONSTANT_NAMES[]{
"worldViewProjectionMatrix",
@@ -197,7 +197,10 @@ namespace IW4
"worldMap",
"worldMapSampler",
};
} // namespace
namespace IW4
{
void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{
for (const auto* zone : ZoneRegistry::GetRegistryForGame(GameId::IW4)->Zones())
@@ -230,7 +233,7 @@ namespace IW4
AddTextureDefName(knownTextureDefName);
}
unsigned MaterialConstantZoneState::HashString(const std::string& str)
unsigned MaterialConstantZoneState::HashString(const std::string& str) const
{
return Common::R_HashString(str.c_str());
}

View File

@@ -11,6 +11,6 @@ namespace IW4
protected:
void ExtractNamesFromZoneInternal() override;
void AddStaticKnownNames() override;
unsigned HashString(const std::string& str) override;
[[nodiscard]] unsigned HashString(const std::string& str) const override;
};
} // namespace IW4

View File

@@ -6,7 +6,7 @@
#include "ObjWriting.h"
#include "Zone/ZoneRegistry.h"
namespace IW5
namespace
{
const char* KNOWN_CONSTANT_NAMES[]{
"worldViewProjectionMatrix",
@@ -197,7 +197,10 @@ namespace IW5
"worldMap",
"worldMapSampler",
};
} // namespace
namespace IW5
{
void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{
for (const auto* zone : ZoneRegistry::GetRegistryForGame(GameId::IW5)->Zones())
@@ -230,7 +233,7 @@ namespace IW5
AddTextureDefName(knownTextureDefName);
}
unsigned MaterialConstantZoneState::HashString(const std::string& str)
unsigned MaterialConstantZoneState::HashString(const std::string& str) const
{
return Common::R_HashString(str.c_str());
}

View File

@@ -11,6 +11,6 @@ namespace IW5
protected:
void ExtractNamesFromZoneInternal() override;
void AddStaticKnownNames() override;
unsigned HashString(const std::string& str) override;
[[nodiscard]] unsigned HashString(const std::string& str) const override;
};
} // namespace IW5

View File

@@ -6,7 +6,7 @@
#include "ObjWriting.h"
#include "Zone/ZoneRegistry.h"
namespace T5
namespace
{
const char* KNOWN_CONSTANT_NAMES[]{
"AngularVelocityScale",
@@ -471,7 +471,10 @@ namespace T5
"ui3d",
"ui3dSampler",
};
} // namespace
namespace T5
{
void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{
for (const auto* zone : ZoneRegistry::GetRegistryForGame(GameId::T5)->Zones())
@@ -493,7 +496,7 @@ namespace T5
}
}
unsigned MaterialConstantZoneState::HashString(const std::string& str)
unsigned MaterialConstantZoneState::HashString(const std::string& str) const
{
return Common::R_HashString(str.c_str());
}

View File

@@ -7,12 +7,12 @@
namespace T5
{
class MaterialConstantZoneState final : public AbstractMaterialConstantZoneStateDx11
class MaterialConstantZoneState final : public AbstractMaterialConstantZoneStateDx9
{
protected:
void ExtractNamesFromZoneInternal() override;
void ExtractNamesFromTechnique(const MaterialTechnique* technique);
void AddStaticKnownNames() override;
unsigned HashString(const std::string& str) override;
[[nodiscard]] unsigned HashString(const std::string& str) const override;
};
} // namespace T5

View File

@@ -6,7 +6,7 @@
#include "ObjWriting.h"
#include "Zone/ZoneRegistry.h"
namespace T6
namespace
{
const char* KNOWN_CONSTANT_NAMES[]{
"AngularVelocityScale",
@@ -471,7 +471,10 @@ namespace T6
"ui3d",
"ui3dSampler",
};
} // namespace
namespace T6
{
void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{
for (const auto* zone : ZoneRegistry::GetRegistryForGame(GameId::T6)->Zones())
@@ -493,7 +496,7 @@ namespace T6
}
}
unsigned MaterialConstantZoneState::HashString(const std::string& str)
unsigned MaterialConstantZoneState::HashString(const std::string& str) const
{
return Common::R_HashString(str.c_str());
}

View File

@@ -13,6 +13,6 @@ namespace T6
void ExtractNamesFromZoneInternal() override;
void ExtractNamesFromTechnique(const MaterialTechnique* technique);
void AddStaticKnownNames() override;
unsigned HashString(const std::string& str) override;
[[nodiscard]] unsigned HashString(const std::string& str) const override;
};
} // namespace T6

View File

@@ -1,5 +1,6 @@
#include "TechsetDumperT6.h"
#include "Game/T6/Material/MaterialConstantZoneStateT6.h"
#include "Game/T6/Techset/TechsetConstantsT6.h"
#include "Shader/ShaderCommon.h"
#include "Techset/CommonTechniqueDumper.h"
@@ -77,6 +78,183 @@ namespace
};
}
techset::CommonShaderArg ConvertToCommonArg(const MaterialShaderArgument& arg)
{
switch (arg.type)
{
case MTL_ARG_CODE_VERTEX_CONST:
case MTL_ARG_CODE_PIXEL_CONST:
return techset::CommonShaderArg{
.m_type = techset::CommonShaderArgType::CODE_CONST,
.m_destination = {.dx11 =
{
.m_location = arg.location.offset,
.m_size = arg.size,
.m_buffer = arg.buffer,
}},
.m_value = {
.code_const_source = static_cast<techset::CommonCodeConstSource>(arg.u.codeConst.index),
}
};
case MTL_ARG_MATERIAL_VERTEX_CONST:
case MTL_ARG_MATERIAL_PIXEL_CONST:
return techset::CommonShaderArg{
.m_type = techset::CommonShaderArgType::MATERIAL_CONST,
.m_destination = {.dx11 =
{
.m_location = arg.location.offset,
.m_size = arg.size,
.m_buffer = arg.buffer,
}},
.m_value = {
.name_hash = arg.u.nameHash,
}
};
case MTL_ARG_CODE_PIXEL_SAMPLER:
return techset::CommonShaderArg{
.m_type = techset::CommonShaderArgType::CODE_SAMPLER,
.m_destination = {.dx11 =
{
.m_location = arg.location.samplerIndex,
.m_size = arg.size,
.m_buffer = arg.buffer,
}},
.m_value = {
.code_sampler_source = static_cast<techset::CommonCodeSamplerSource>(arg.u.codeSampler),
}
};
case MTL_ARG_MATERIAL_PIXEL_SAMPLER:
return techset::CommonShaderArg{
.m_type = techset::CommonShaderArgType::MATERIAL_SAMPLER,
.m_destination = {.dx11 =
{
.m_location = arg.location.samplerIndex,
.m_size = arg.size,
.m_buffer = arg.buffer,
}},
.m_value = {
.name_hash = arg.u.nameHash,
}
};
default:
case MTL_ARG_LITERAL_VERTEX_CONST:
case MTL_ARG_LITERAL_PIXEL_CONST:
if (arg.u.literalConst)
{
return techset::CommonShaderArg{
.m_type = techset::CommonShaderArgType::LITERAL_CONST,
.m_destination = {.dx11 =
{
.m_location = arg.location.offset,
.m_size = arg.size,
.m_buffer = arg.buffer,
}},
.m_value = {
.literal_value =
{
(*arg.u.literalConst)[0],
(*arg.u.literalConst)[1],
(*arg.u.literalConst)[2],
(*arg.u.literalConst)[3],
}, }
};
}
return techset::CommonShaderArg{
.m_type = techset::CommonShaderArgType::LITERAL_CONST,
.m_destination = {.dx11 =
{
.m_location = arg.location.offset,
.m_size = arg.size,
.m_buffer = arg.buffer,
}},
.m_value = {},
};
}
}
techset::CommonTechniqueShader ConvertToCommonShader(const MaterialPass& pass, const MaterialVertexShader* vertexShader)
{
techset::CommonTechniqueShader result{};
if (!vertexShader)
return result;
if (vertexShader->name)
result.m_name = vertexShader->name;
if (vertexShader->prog.loadDef.program)
{
result.m_shader_bin = vertexShader->prog.loadDef.program;
result.m_shader_bin_size = vertexShader->prog.loadDef.programSize;
}
if (pass.args)
{
const size_t totalArgCount = pass.perPrimArgCount + pass.perObjArgCount + pass.stableArgCount;
for (auto argIndex = 0uz; argIndex < totalArgCount; argIndex++)
{
const auto& arg = pass.args[argIndex];
switch (arg.type)
{
case MTL_ARG_CODE_VERTEX_CONST:
case MTL_ARG_MATERIAL_VERTEX_CONST:
case MTL_ARG_LITERAL_VERTEX_CONST:
result.m_args.emplace_back(ConvertToCommonArg(arg));
break;
default:
break;
}
}
}
return result;
}
techset::CommonTechniqueShader ConvertToCommonShader(const MaterialPass& pass, const MaterialPixelShader* pixelShader)
{
techset::CommonTechniqueShader result{};
if (!pixelShader)
return result;
if (pixelShader->name)
result.m_name = pixelShader->name;
if (pixelShader->prog.loadDef.program)
{
result.m_shader_bin = pixelShader->prog.loadDef.program;
result.m_shader_bin_size = pixelShader->prog.loadDef.programSize;
}
if (pass.args)
{
const size_t totalArgCount = pass.perPrimArgCount + pass.perObjArgCount + pass.stableArgCount;
for (auto argIndex = 0uz; argIndex < totalArgCount; argIndex++)
{
const auto& arg = pass.args[argIndex];
switch (arg.type)
{
case MTL_ARG_CODE_PIXEL_CONST:
case MTL_ARG_CODE_PIXEL_SAMPLER:
case MTL_ARG_MATERIAL_PIXEL_CONST:
case MTL_ARG_MATERIAL_PIXEL_SAMPLER:
case MTL_ARG_LITERAL_PIXEL_CONST:
result.m_args.emplace_back(ConvertToCommonArg(arg));
break;
default:
break;
}
}
}
return result;
}
techset::CommonTechnique ConvertToCommonTechnique(const MaterialTechnique& technique)
{
std::vector<techset::CommonPass> passes;
@@ -85,38 +263,11 @@ namespace
{
const auto& pass = technique.passArray[passIndex];
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,
.m_vertex_shader = ConvertToCommonShader(pass, pass.vertexShader),
.m_pixel_shader = ConvertToCommonShader(pass, pass.pixelShader),
.m_vertex_declaration = ConvertToCommonVertexDeclaration(pass.vertexDecl),
});
}
@@ -130,17 +281,22 @@ namespace
void DumpTechniques(AssetDumpingContext& context, const MaterialTechniqueSet& techset)
{
static techset::CommonCodeSourceInfos codeSourceInfos(commonCodeConstSources,
std::extent_v<decltype(commonCodeConstSources)>,
commonCodeSamplerSources,
std::extent_v<decltype(commonCodeSamplerSources)>);
static techset::CommonStreamRoutingInfos routingInfos(
streamRoutingSources, std::extent_v<decltype(streamRoutingSources)>, streamRoutingDestinations, std::extent_v<decltype(streamRoutingDestinations)>);
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);
techset::DumpCommonTechnique(routingInfos, context, commonTechnique);
techset::DumpCommonTechnique(context, commonTechnique, codeSourceInfos, routingInfos, *materialConstantState);
}
}
}
@@ -178,6 +334,12 @@ namespace techset
{
}
void DumperT6::Dump(AssetDumpingContext& context)
{
context.GetZoneAssetDumperState<MaterialConstantZoneState>()->EnsureInitialized();
AbstractAssetDumper::Dump(context);
}
void DumperT6::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetTechniqueSet::Type>& asset)
{
const auto* techniqueSet = asset.Asset();

View File

@@ -10,6 +10,8 @@ namespace techset
public:
explicit DumperT6(const AssetPool<T6::AssetTechniqueSet::Type>& pool);
void Dump(AssetDumpingContext& context) override;
protected:
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<T6::AssetTechniqueSet::Type>& asset) override;
};

View File

@@ -9,13 +9,22 @@
namespace
{
constexpr const char* SAMPLER_STR = "Sampler";
constexpr const char* GLOBALS_CBUFFER_NAME = "$Globals";
constexpr const char* PER_OBJECT_CONSTS_CBUFFER_NAME = "PerObjectConsts";
constexpr auto SAMPLER_STR = "Sampler";
constexpr auto GLOBALS_CBUFFER_NAME = "$Globals";
constexpr auto PER_PRIM_CONSTS_CBUFFER_NAME = "PerPrimConsts";
constexpr auto PER_OBJECT_CONSTS_CBUFFER_NAME = "PerObjectConsts";
} // namespace
void AbstractMaterialConstantZoneState::ExtractNamesFromZone()
AbstractMaterialConstantZoneState::AbstractMaterialConstantZoneState()
: m_initialized(false)
{
}
void AbstractMaterialConstantZoneState::EnsureInitialized()
{
if (m_initialized)
return;
con::debug("Building material constant name lookup...");
const auto begin = std::chrono::high_resolution_clock::now();
@@ -31,6 +40,8 @@ void AbstractMaterialConstantZoneState::ExtractNamesFromZone()
durationInMs.count(),
m_constant_names_from_shaders.size(),
m_texture_def_names_from_shaders.size());
m_initialized = true;
}
bool AbstractMaterialConstantZoneState::GetConstantName(const unsigned hash, std::string& constantName) const
@@ -124,6 +135,12 @@ void AbstractMaterialConstantZoneStateDx11::ExtractNamesFromShader(const void* s
return constantBuffer.m_name == GLOBALS_CBUFFER_NAME;
});
const auto perPrimConsts = std::ranges::find_if(std::as_const(shaderInfo->m_constant_buffers),
[](const d3d11::ConstantBuffer& constantBuffer)
{
return constantBuffer.m_name == PER_PRIM_CONSTS_CBUFFER_NAME;
});
const auto perObjectConsts = std::ranges::find_if(std::as_const(shaderInfo->m_constant_buffers),
[](const d3d11::ConstantBuffer& constantBuffer)
{
@@ -136,6 +153,12 @@ void AbstractMaterialConstantZoneStateDx11::ExtractNamesFromShader(const void* s
AddConstantName(variable.m_name);
}
if (perPrimConsts != shaderInfo->m_constant_buffers.end())
{
for (const auto& variable : perPrimConsts->m_variables)
AddConstantName(variable.m_name);
}
if (perObjectConsts != shaderInfo->m_constant_buffers.end())
{
for (const auto& variable : perObjectConsts->m_variables)

View File

@@ -9,20 +9,24 @@
class AbstractMaterialConstantZoneState : public IZoneAssetDumperState
{
public:
void ExtractNamesFromZone();
void EnsureInitialized();
bool GetConstantName(unsigned hash, std::string& constantName) const;
bool GetTextureDefName(unsigned hash, std::string& textureDefName) const;
[[nodiscard]] virtual unsigned HashString(const std::string& str) const = 0;
protected:
AbstractMaterialConstantZoneState();
virtual void ExtractNamesFromShader(const void* shader, size_t shaderSize) = 0;
virtual void ExtractNamesFromZoneInternal() = 0;
virtual void AddStaticKnownNames() = 0;
virtual unsigned HashString(const std::string& str) = 0;
bool ShouldDumpFromStruct(const void* pStruct);
void AddConstantName(const std::string& constantName);
bool AddTextureDefName(const std::string& textureDefName);
bool m_initialized;
std::unordered_set<const void*> m_dumped_structs;
std::unordered_map<unsigned, std::string> m_constant_names_from_shaders;
std::unordered_map<unsigned, std::string> m_texture_def_names_from_shaders;

View File

@@ -369,7 +369,7 @@ namespace material
void CLASS_NAME::Dump(AssetDumpingContext& context)
{
auto* materialConstantState = context.GetZoneAssetDumperState<MaterialConstantZoneState>();
materialConstantState->ExtractNamesFromZone();
materialConstantState->EnsureInitialized();
AbstractAssetDumper::Dump(context);
}

View File

@@ -4,6 +4,7 @@
#include "Shader/D3D11ShaderAnalyser.h"
#include "Shader/D3D9ShaderAnalyser.h"
#include "Techset/TechsetCommon.h"
#include "Utils/Logging/Log.h"
#include <cassert>
#include <cstdint>
@@ -21,9 +22,14 @@ namespace
class TechniqueFileWriter : public AbstractTextDumper
{
public:
TechniqueFileWriter(const CommonStreamRoutingInfos& routingInfos, std::ostream& stream)
TechniqueFileWriter(std::ostream& stream,
const CommonCodeSourceInfos& codeSourceInfos,
const CommonStreamRoutingInfos& routingInfos,
const AbstractMaterialConstantZoneState& constantZoneState)
: AbstractTextDumper(stream),
m_routing_infos(routingInfos)
m_code_source_infos(codeSourceInfos),
m_routing_infos(routingInfos),
m_constant_zone_state(constantZoneState)
{
}
@@ -45,11 +51,11 @@ namespace
#endif
for (const auto& pass : technique.m_passes)
DumpPass(pass);
DumpPass(technique, pass);
}
private:
void DumpPass(const CommonPass& pass)
void DumpPass(const CommonTechnique& technique, const CommonPass& pass)
{
m_stream << "{\n";
IncIndent();
@@ -67,8 +73,8 @@ namespace
#endif
DumpStateMap();
DumpShader(pass.m_vertex_shader, TechniqueShaderType::VERTEX_SHADER, pass.m_dx_version);
DumpShader(pass.m_pixel_shader, TechniqueShaderType::PIXEL_SHADER, pass.m_dx_version);
DumpShader(technique, pass.m_vertex_shader, TechniqueShaderType::VERTEX_SHADER, pass.m_dx_version);
DumpShader(technique, pass.m_pixel_shader, TechniqueShaderType::PIXEL_SHADER, pass.m_dx_version);
DumpVertexDecl(pass.m_vertex_declaration);
DecIndent();
@@ -83,12 +89,15 @@ namespace
m_stream << "stateMap \"passthrough\"; // TODO\n";
}
void DumpShader(const CommonTechniqueShader& shader, const TechniqueShaderType shaderType, const DxVersion dxVersion) const
void DumpShader(const CommonTechnique& technique, const CommonTechniqueShader& shader, const TechniqueShaderType shaderType, const DxVersion dxVersion)
{
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);
{
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);
}
return;
}
@@ -103,6 +112,11 @@ namespace
versionMajor = shaderInfo->m_version_major;
versionMinor = shaderInfo->m_version_minor;
DumpShaderHeader(shader, shaderType, versionMajor, versionMinor);
for (const auto& arg : shader.m_args)
DumpShaderArgDx9(technique, arg, *shaderInfo);
}
else
{
@@ -114,8 +128,20 @@ namespace
versionMajor = shaderInfo->m_version_major;
versionMinor = shaderInfo->m_version_minor;
DumpShaderHeader(shader, shaderType, versionMajor, versionMinor);
for (const auto& arg : shader.m_args)
DumpShaderArgDx11(technique, arg, *shaderInfo);
}
DecIndent();
Indent();
m_stream << "}\n";
}
void DumpShaderHeader(const CommonTechniqueShader& shader, const TechniqueShaderType shaderType, unsigned versionMajor, unsigned versionMinor)
{
const auto shaderTypeName = shaderType == TechniqueShaderType::VERTEX_SHADER ? "vertexShader" : "pixelShader";
m_stream << "\n";
@@ -123,9 +149,225 @@ namespace
m_stream << std::format("{} {}.{} \"{}\"\n", shaderTypeName, versionMajor, versionMinor, shader.m_name);
Indent();
m_stream << "{\n";
IncIndent();
}
Indent();
m_stream << "}\n";
void DumpShaderArgDx9(const CommonTechnique& technique, const CommonShaderArg& arg, const d3d9::ShaderInfo& shaderInfo) const
{
const auto expectedRegisterSet = arg.m_type == CommonShaderArgType::CODE_SAMPLER || arg.m_type == CommonShaderArgType::MATERIAL_SAMPLER
? d3d9::RegisterSet::SAMPLER
: d3d9::RegisterSet::FLOAT_4;
const auto destinationRegister = arg.m_destination.dx9.m_destination_register;
const auto targetShaderArg = std::ranges::find_if(shaderInfo.m_constants,
[destinationRegister, expectedRegisterSet](const d3d9::ShaderConstant& constant)
{
return constant.m_register_set == expectedRegisterSet
&& constant.m_register_index <= destinationRegister
&& constant.m_register_index + constant.m_register_count > destinationRegister;
});
assert(targetShaderArg != shaderInfo.m_constants.end());
if (targetShaderArg == shaderInfo.m_constants.end())
{
Indent();
m_stream << std::format("// Unrecognized arg dest: {} type: {}\n", destinationRegister, static_cast<unsigned>(arg.m_type));
con::error("Technique {}: Could not find arg (type: {}; dest: {}) in shader",
technique.m_name,
destinationRegister,
static_cast<unsigned>(arg.m_type));
return;
}
std::string codeDestAccessor;
if (targetShaderArg->m_type_elements > 1)
{
codeDestAccessor = std::format("{}[{}]", targetShaderArg->m_name, destinationRegister - targetShaderArg->m_register_index);
}
else
codeDestAccessor = targetShaderArg->m_name;
DumpShaderArg(technique, arg, codeDestAccessor);
}
void DumpShaderArgDx11(const CommonTechnique& technique, const CommonShaderArg& arg, const d3d11::ShaderInfo& shaderInfo) const
{
const auto& destination = arg.m_destination.dx11;
if (arg.m_type == CommonShaderArgType::CODE_CONST || arg.m_type == CommonShaderArgType::MATERIAL_CONST
|| arg.m_type == CommonShaderArgType::LITERAL_CONST)
{
const auto boundResource = std::ranges::find_if(shaderInfo.m_bound_resources,
[destination](const d3d11::BoundResource& resource)
{
return resource.m_type == d3d11::BoundResourceType::CBUFFER
&& resource.m_bind_point >= destination.m_buffer
&& resource.m_bind_point + resource.m_bind_count > destination.m_buffer;
});
if (boundResource == shaderInfo.m_bound_resources.end())
{
Indent();
m_stream << std::format("// Could not find bound resource for arg buffer: {} offset: {} type: {}\n",
destination.m_buffer,
destination.m_location,
static_cast<unsigned>(arg.m_type));
con::error("Technique {}: Could not find bound resource for arg (buffer: {} offset: {} type: {}) in shader",
technique.m_name,
destination.m_buffer,
destination.m_location,
static_cast<unsigned>(arg.m_type));
return;
}
const auto buffer = std::ranges::find_if(shaderInfo.m_constant_buffers,
[&boundResource](const d3d11::ConstantBuffer& constantBuffer)
{
return constantBuffer.m_name == boundResource->m_name;
});
if (buffer == shaderInfo.m_constant_buffers.end())
{
Indent();
m_stream << std::format("// Could not find buffer for bound resource: {}\n", boundResource->m_name);
con::error("Technique {}: Could not find buffer for bound resource: {} in shader", technique.m_name, boundResource->m_name);
return;
}
const auto variable = std::ranges::find_if(buffer->m_variables,
[destination](const d3d11::ConstantBufferVariable& var)
{
return var.m_offset <= destination.m_location
&& var.m_offset + var.m_size >= destination.m_location + destination.m_size;
});
if (variable == buffer->m_variables.end())
{
Indent();
m_stream << std::format("// Could not find variable in buffer: {} offset: {} type: {}\n",
buffer->m_name,
destination.m_location,
static_cast<unsigned>(arg.m_type));
con::error("Technique {}: Could not find variable in buffer for arg (buffer: {} offset: {} type: {}) in shader",
technique.m_name,
buffer->m_name,
destination.m_location,
static_cast<unsigned>(arg.m_type));
return;
}
DumpShaderArg(technique, arg, variable->m_name);
}
else
{
assert(arg.m_type == CommonShaderArgType::CODE_SAMPLER || arg.m_type == CommonShaderArgType::MATERIAL_SAMPLER);
const auto boundResource = std::ranges::find_if(shaderInfo.m_bound_resources,
[destination](const d3d11::BoundResource& resource)
{
return (resource.m_type == d3d11::BoundResourceType::SAMPLER
|| resource.m_type == d3d11::BoundResourceType::TEXTURE)
&& resource.m_bind_point == destination.m_location;
});
if (boundResource == shaderInfo.m_bound_resources.end())
{
Indent();
m_stream << std::format("// Could not find buffer for arg buffer: {} offset: {} type: {}\n",
destination.m_buffer,
destination.m_location,
static_cast<unsigned>(arg.m_type));
con::error("Technique {}: Could not find buffer for arg (buffer: {} offset: {} type: {}) in shader",
technique.m_name,
destination.m_buffer,
destination.m_location,
static_cast<unsigned>(arg.m_type));
return;
}
DumpShaderArg(technique, arg, boundResource->m_name);
}
}
void DumpShaderArg(const CommonTechnique& technique, const CommonShaderArg& arg, std::string codeDestAccessor) const
{
if (arg.m_type == CommonShaderArgType::CODE_CONST)
{
const auto constSourceInfo = m_code_source_infos.GetInfoForCodeConstSource(arg.m_value.code_const_source);
if (constSourceInfo)
{
if (codeDestAccessor != constSourceInfo->accessor)
{
Indent();
m_stream << std::format("{} = constant.{};\n", codeDestAccessor, constSourceInfo->accessor);
}
else
{
#ifdef TECHSET_DEBUG
Indent();
m_stream << std::format("// Omitted due to matching accessors: {} = constant.{};\n", codeDestAccessor, constSourceInfo->accessor);
#endif
}
}
else
{
assert(false);
Indent();
m_stream << std::format("// ERROR: Could not find code source info for const: {}\n", codeDestAccessor);
con::error("Technique {}: Could not find code source info for const {}", technique.m_name, codeDestAccessor);
}
}
else if (arg.m_type == CommonShaderArgType::CODE_SAMPLER)
{
const auto samplerSourceInfo = m_code_source_infos.GetInfoForCodeSamplerSource(arg.m_value.code_sampler_source);
if (samplerSourceInfo)
{
if (codeDestAccessor != samplerSourceInfo->accessor)
{
Indent();
m_stream << std::format("{} = sampler.{};\n", codeDestAccessor, samplerSourceInfo->accessor);
}
else
{
#ifdef TECHSET_DEBUG
Indent();
m_stream << std::format("// Omitted due to matching accessors: {} = sampler.{};\n", codeDestAccessor, samplerSourceInfo->accessor);
#endif
}
}
else
{
assert(false);
Indent();
m_stream << std::format("// ERROR: Could not find code source info for sampler: {}\n", codeDestAccessor);
con::error("Technique {}: Could not find code source info for sampler {}", technique.m_name, codeDestAccessor);
}
}
else if (arg.m_type == CommonShaderArgType::LITERAL_CONST)
{
Indent();
m_stream << std::format("{} = float4({}, {}, {}, {});\n",
codeDestAccessor,
arg.m_value.literal_value[0],
arg.m_value.literal_value[1],
arg.m_value.literal_value[2],
arg.m_value.literal_value[3]);
}
else if (arg.m_type == CommonShaderArgType::MATERIAL_CONST || arg.m_type == CommonShaderArgType::MATERIAL_SAMPLER)
{
Indent();
std::string materialPropertyName;
if (m_constant_zone_state.GetConstantName(arg.m_value.name_hash, materialPropertyName)
|| m_constant_zone_state.GetTextureDefName(arg.m_value.name_hash, materialPropertyName))
{
m_stream << std::format("{} = material.{};\n", codeDestAccessor, materialPropertyName);
}
else if (m_constant_zone_state.HashString(codeDestAccessor) == arg.m_value.name_hash)
{
m_stream << std::format("{} = material.{};\n", codeDestAccessor, codeDestAccessor);
}
else
{
m_stream << std::format("{} = material.#0x{:x};\n", codeDestAccessor, arg.m_value.name_hash);
}
}
else
{
assert(false);
}
}
void DumpVertexDecl(const CommonVertexDeclaration& vertexDeclaration) const
@@ -143,18 +385,24 @@ namespace
}
}
const CommonCodeSourceInfos& m_code_source_infos;
const CommonStreamRoutingInfos& m_routing_infos;
const AbstractMaterialConstantZoneState& m_constant_zone_state;
};
} // namespace
namespace techset
{
void DumpCommonTechnique(const CommonStreamRoutingInfos& routingInfos, const AssetDumpingContext& context, const CommonTechnique& technique)
void DumpCommonTechnique(const AssetDumpingContext& context,
const CommonTechnique& technique,
const CommonCodeSourceInfos& codeSourceInfos,
const CommonStreamRoutingInfos& routingInfos,
const AbstractMaterialConstantZoneState& constantZoneState)
{
const auto techniqueFile = context.OpenAssetFile(GetFileNameForTechniqueName(technique.m_name));
if (techniqueFile)
{
TechniqueFileWriter writer(routingInfos, *techniqueFile);
TechniqueFileWriter writer(*techniqueFile, codeSourceInfos, routingInfos, constantZoneState);
writer.DumpTechnique(technique);
}
}

View File

@@ -1,9 +1,14 @@
#pragma once
#include "Dumping/AssetDumpingContext.h"
#include "Material/AbstractMaterialConstantZoneState.h"
#include "Techset/CommonTechnique.h"
namespace techset
{
void DumpCommonTechnique(const CommonStreamRoutingInfos& routingInfos, const AssetDumpingContext& context, const CommonTechnique& technique);
void DumpCommonTechnique(const AssetDumpingContext& context,
const CommonTechnique& technique,
const CommonCodeSourceInfos& codeSourceInfos,
const CommonStreamRoutingInfos& routingInfos,
const AbstractMaterialConstantZoneState& constantZoneState);
} // namespace techset