chore: generalize material constant zone state

This commit is contained in:
Jan 2024-09-22 15:10:01 +02:00
parent 88499b6428
commit 3b59dad109
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
7 changed files with 229 additions and 143 deletions

View File

@ -21,6 +21,11 @@ namespace T6
return hash; return hash;
} }
static constexpr uint32_t R_HashString(const char* string)
{
return R_HashString(string, 0u);
}
static constexpr uint32_t SND_HashName(const char* str) static constexpr uint32_t SND_HashName(const char* str)
{ {
if (!str || !*str) if (!str || !*str)

View File

@ -61,12 +61,12 @@ namespace d3d9
uint32_t TypeInfo; uint32_t TypeInfo;
}; };
bool PopulateVersionInfo(ShaderInfo& shaderInfo, const uint32_t* shaderByteCode, const size_t shaderByteCodeSize) bool PopulateVersionInfo(ShaderInfo& shaderInfo, const void* shaderByteCode, const size_t shaderByteCodeSize)
{ {
if (shaderByteCodeSize < sizeof(uint32_t)) if (shaderByteCodeSize < sizeof(uint32_t))
return false; return false;
const auto version = *shaderByteCode; const auto version = *static_cast<const uint32_t*>(shaderByteCode);
shaderInfo.m_version_minor = version & 0xFF; shaderInfo.m_version_minor = version & 0xFF;
shaderInfo.m_version_major = (version & 0xFF00) >> 8; shaderInfo.m_version_major = (version & 0xFF00) >> 8;
@ -91,10 +91,10 @@ namespace d3d9
return false; return false;
} }
bool FindComment(const uint32_t* shaderByteCode, const size_t shaderByteCodeSize, const uint32_t magic, const char*& commentStart, size_t& commentSize) bool FindComment(const uint8_t* shaderByteCode, const size_t shaderByteCodeSize, const uint32_t magic, const char*& commentStart, size_t& commentSize)
{ {
const uint32_t* currentPos = shaderByteCode + 1; const auto* currentPos = reinterpret_cast<const uint32_t*>(shaderByteCode + sizeof(uint32_t));
size_t currentOffset = sizeof(uint32_t); auto currentOffset = sizeof(uint32_t);
while (*currentPos != OPCODE_END && (currentOffset + sizeof(uint32_t) - 1) < shaderByteCodeSize) while (*currentPos != OPCODE_END && (currentOffset + sizeof(uint32_t) - 1) < shaderByteCodeSize)
{ {
const auto currentValue = *currentPos; const auto currentValue = *currentPos;
@ -215,7 +215,7 @@ namespace d3d9
return true; return true;
} }
bool PopulateShaderInfoFromShaderByteCode(ShaderInfo& shaderInfo, const uint32_t* shaderByteCode, const size_t shaderByteCodeSize) bool PopulateShaderInfoFromShaderByteCode(ShaderInfo& shaderInfo, const uint8_t* shaderByteCode, const size_t shaderByteCodeSize)
{ {
if (!PopulateVersionInfo(shaderInfo, shaderByteCode, shaderByteCodeSize)) if (!PopulateVersionInfo(shaderInfo, shaderByteCode, shaderByteCodeSize))
return false; return false;
@ -236,14 +236,14 @@ namespace d3d9
} }
} // namespace d3d9 } // namespace d3d9
std::unique_ptr<ShaderInfo> ShaderAnalyser::GetShaderInfo(const uint32_t* shaderByteCode, const size_t shaderByteCodeSize) std::unique_ptr<ShaderInfo> ShaderAnalyser::GetShaderInfo(const void* shaderByteCode, const size_t shaderByteCodeSize)
{ {
if (shaderByteCode == nullptr || shaderByteCodeSize == 0) if (shaderByteCode == nullptr || shaderByteCodeSize == 0)
return nullptr; return nullptr;
auto shaderInfo = std::make_unique<ShaderInfo>(); auto shaderInfo = std::make_unique<ShaderInfo>();
if (!PopulateShaderInfoFromShaderByteCode(*shaderInfo, shaderByteCode, shaderByteCodeSize)) if (!PopulateShaderInfoFromShaderByteCode(*shaderInfo, static_cast<const uint8_t*>(shaderByteCode), shaderByteCodeSize))
return nullptr; return nullptr;
return shaderInfo; return shaderInfo;

View File

@ -95,6 +95,6 @@ namespace d3d9
class ShaderAnalyser class ShaderAnalyser
{ {
public: public:
static std::unique_ptr<ShaderInfo> GetShaderInfo(const uint32_t* shaderByteCode, size_t shaderByteCodeSize); static std::unique_ptr<ShaderInfo> GetShaderInfo(const void* shaderByteCode, size_t shaderByteCodeSize);
}; };
} // namespace d3d9 } // namespace d3d9

View File

@ -4,16 +4,9 @@
#include "Game/T6/GameAssetPoolT6.h" #include "Game/T6/GameAssetPoolT6.h"
#include "Game/T6/GameT6.h" #include "Game/T6/GameT6.h"
#include "ObjWriting.h" #include "ObjWriting.h"
#include "Shader/D3D11ShaderAnalyser.h"
#include <chrono>
namespace T6 namespace T6
{ {
static constexpr const char* SAMPLER_STR = "Sampler";
static constexpr const char* GLOBALS_CBUFFER_NAME = "$Globals";
static constexpr const char* PER_OBJECT_CONSTS_CBUFFER_NAME = "PerObjectConsts";
const char* KNOWN_CONSTANT_NAMES[]{ const char* KNOWN_CONSTANT_NAMES[]{
"AngularVelocityScale", "AngularVelocityScale",
"AnimSpeed", "AnimSpeed",
@ -478,15 +471,8 @@ namespace T6
"ui3dSampler", "ui3dSampler",
}; };
void MaterialConstantZoneState::ExtractNamesFromZone() void MaterialConstantZoneState::ExtractNamesFromZoneInternal()
{ {
if (ObjWriting::Configuration.Verbose)
std::cout << "Building material constant name lookup...\n";
const auto begin = std::chrono::high_resolution_clock::now();
AddStaticKnownNames();
for (const auto* zone : g_GameT6.GetZones()) for (const auto* zone : g_GameT6.GetZones())
{ {
const auto* t6AssetPools = dynamic_cast<const GameAssetPoolT6*>(zone->m_pools.get()); const auto* t6AssetPools = dynamic_cast<const GameAssetPoolT6*>(zone->m_pools.get());
@ -504,49 +490,18 @@ namespace T6
} }
} }
} }
const auto end = std::chrono::high_resolution_clock::now();
if (ObjWriting::Configuration.Verbose)
{
const auto durationInMs = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
std::cout << "Built material constant name lookup in " << durationInMs.count() << "ms: " << m_constant_names_from_shaders.size()
<< " constant names; " << m_texture_def_names_from_shaders.size() << " texture def names\n";
}
} }
bool MaterialConstantZoneState::GetConstantName(const unsigned hash, std::string& constantName) const unsigned MaterialConstantZoneState::HashString(const std::string& str)
{ {
const auto existingConstantName = m_constant_names_from_shaders.find(hash); return Common::R_HashString(str.c_str());
if (existingConstantName != m_constant_names_from_shaders.end())
{
constantName = existingConstantName->second;
return true;
}
return false;
}
bool MaterialConstantZoneState::GetTextureDefName(const unsigned hash, std::string& textureDefName) const
{
const auto existingTextureDefName = m_texture_def_names_from_shaders.find(hash);
if (existingTextureDefName != m_texture_def_names_from_shaders.end())
{
textureDefName = existingTextureDefName->second;
return true;
}
return false;
} }
void MaterialConstantZoneState::ExtractNamesFromTechnique(const MaterialTechnique* technique) void MaterialConstantZoneState::ExtractNamesFromTechnique(const MaterialTechnique* technique)
{ {
const auto existingTechnique = m_dumped_techniques.find(technique); if (!ShouldDumpFromStruct(technique))
if (existingTechnique != m_dumped_techniques.end())
return; return;
m_dumped_techniques.emplace(technique);
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++) for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
{ {
const auto& pass = technique->passArray[passIndex]; const auto& pass = technique->passArray[passIndex];
@ -559,54 +514,6 @@ namespace T6
} }
} }
void MaterialConstantZoneState::ExtractNamesFromShader(const char* shader, const size_t shaderSize)
{
const auto shaderInfo = d3d11::ShaderAnalyser::GetShaderInfo(reinterpret_cast<const uint8_t*>(shader), shaderSize);
if (!shaderInfo)
return;
const auto globalsConstantBuffer = std::ranges::find_if(std::as_const(shaderInfo->m_constant_buffers),
[](const d3d11::ConstantBuffer& constantBuffer)
{
return constantBuffer.m_name == GLOBALS_CBUFFER_NAME;
});
const auto perObjectConsts = std::ranges::find_if(std::as_const(shaderInfo->m_constant_buffers),
[](const d3d11::ConstantBuffer& constantBuffer)
{
return constantBuffer.m_name == PER_OBJECT_CONSTS_CBUFFER_NAME;
});
if (globalsConstantBuffer != shaderInfo->m_constant_buffers.end())
{
for (const auto& variable : globalsConstantBuffer->m_variables)
AddConstantName(variable.m_name);
}
if (perObjectConsts != shaderInfo->m_constant_buffers.end())
{
for (const auto& variable : perObjectConsts->m_variables)
AddConstantName(variable.m_name);
}
for (const auto& boundResource : shaderInfo->m_bound_resources)
{
if (boundResource.m_type == d3d11::BoundResourceType::SAMPLER || boundResource.m_type == d3d11::BoundResourceType::TEXTURE)
{
if (AddTextureDefName(boundResource.m_name))
{
const auto samplerPos = boundResource.m_name.rfind(SAMPLER_STR);
if (samplerPos != std::string::npos)
{
auto nameWithoutSamplerStr = boundResource.m_name;
nameWithoutSamplerStr.erase(samplerPos, std::char_traits<char>::length(SAMPLER_STR));
AddTextureDefName(std::move(nameWithoutSamplerStr));
}
}
}
}
}
void MaterialConstantZoneState::AddStaticKnownNames() void MaterialConstantZoneState::AddStaticKnownNames()
{ {
for (const auto* knownConstantName : KNOWN_CONSTANT_NAMES) for (const auto* knownConstantName : KNOWN_CONSTANT_NAMES)
@ -614,23 +521,4 @@ namespace T6
for (const auto* knownTextureDefName : KNOWN_TEXTURE_DEF_NAMES) for (const auto* knownTextureDefName : KNOWN_TEXTURE_DEF_NAMES)
AddTextureDefName(knownTextureDefName); AddTextureDefName(knownTextureDefName);
} }
void MaterialConstantZoneState::AddConstantName(std::string constantName)
{
const auto hash = Common::R_HashString(constantName.c_str(), 0);
if (m_constant_names_from_shaders.contains(hash))
return;
m_constant_names_from_shaders.emplace(hash, std::move(constantName));
}
bool MaterialConstantZoneState::AddTextureDefName(std::string textureDefName)
{
const auto hash = Common::R_HashString(textureDefName.c_str(), 0);
if (m_texture_def_names_from_shaders.contains(hash))
return false;
m_texture_def_names_from_shaders.emplace(hash, std::move(textureDefName));
return true;
}
} // namespace T6 } // namespace T6

View File

@ -1,30 +1,18 @@
#pragma once #pragma once
#include "Dumping/IZoneAssetDumperState.h"
#include "Game/T6/T6.h" #include "Game/T6/T6.h"
#include "Material/AbstractMaterialConstantZoneState.h"
#include <string> #include <string>
#include <unordered_map>
#include <unordered_set>
namespace T6 namespace T6
{ {
class MaterialConstantZoneState final : public IZoneAssetDumperState class MaterialConstantZoneState final : public AbstractMaterialConstantZoneStateDx11
{ {
public: protected:
void ExtractNamesFromZone(); void ExtractNamesFromZoneInternal() override;
bool GetConstantName(unsigned hash, std::string& constantName) const;
bool GetTextureDefName(unsigned hash, std::string& textureDefName) const;
private:
void ExtractNamesFromTechnique(const MaterialTechnique* technique); void ExtractNamesFromTechnique(const MaterialTechnique* technique);
void ExtractNamesFromShader(const char* shader, size_t shaderSize); void AddStaticKnownNames() override;
void AddStaticKnownNames(); unsigned HashString(const std::string& str) override;
void AddConstantName(std::string constantName);
bool AddTextureDefName(std::string textureDefName);
std::unordered_set<const MaterialTechnique*> m_dumped_techniques;
std::unordered_map<unsigned, std::string> m_constant_names_from_shaders;
std::unordered_map<unsigned, std::string> m_texture_def_names_from_shaders;
}; };
} // namespace T6 } // namespace T6

View File

@ -0,0 +1,164 @@
#include "AbstractMaterialConstantZoneState.h"
#include "ObjWriting.h"
#include "Shader/D3D11ShaderAnalyser.h"
#include "Shader/D3D9ShaderAnalyser.h"
#include <chrono>
namespace
{
constexpr const char* SAMPLER_STR = "Sampler";
constexpr const char* GLOBALS_CBUFFER_NAME = "$Globals";
constexpr const char* PER_OBJECT_CONSTS_CBUFFER_NAME = "PerObjectConsts";
} // namespace
void AbstractMaterialConstantZoneState::ExtractNamesFromZone()
{
if (ObjWriting::Configuration.Verbose)
std::cout << "Building material constant name lookup...\n";
const auto begin = std::chrono::high_resolution_clock::now();
AddStaticKnownNames();
ExtractNamesFromZoneInternal();
const auto end = std::chrono::high_resolution_clock::now();
if (ObjWriting::Configuration.Verbose)
{
const auto durationInMs = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
std::cout << std::format("Built material constant name lookup in {}ms: {} constant names; {} texture def names\n",
durationInMs.count(),
m_constant_names_from_shaders.size(),
m_texture_def_names_from_shaders.size());
}
}
bool AbstractMaterialConstantZoneState::GetConstantName(const unsigned hash, std::string& constantName) const
{
const auto existingConstantName = m_constant_names_from_shaders.find(hash);
if (existingConstantName != m_constant_names_from_shaders.end())
{
constantName = existingConstantName->second;
return true;
}
return false;
}
bool AbstractMaterialConstantZoneState::GetTextureDefName(const unsigned hash, std::string& textureDefName) const
{
const auto existingTextureDefName = m_texture_def_names_from_shaders.find(hash);
if (existingTextureDefName != m_texture_def_names_from_shaders.end())
{
textureDefName = existingTextureDefName->second;
return true;
}
return false;
}
bool AbstractMaterialConstantZoneState::ShouldDumpFromStruct(const void* pStruct)
{
const auto existingTextureDefName = m_dumped_structs.find(pStruct);
if (existingTextureDefName != m_dumped_structs.end())
return false;
m_dumped_structs.emplace(pStruct);
return true;
}
void AbstractMaterialConstantZoneState::AddConstantName(const std::string& constantName)
{
const auto hash = HashString(constantName);
if (m_constant_names_from_shaders.contains(hash))
return;
m_constant_names_from_shaders.emplace(hash, constantName);
}
bool AbstractMaterialConstantZoneState::AddTextureDefName(const std::string& textureDefName)
{
const auto hash = HashString(textureDefName);
if (m_texture_def_names_from_shaders.contains(hash))
return false;
m_texture_def_names_from_shaders.emplace(hash, textureDefName);
return true;
}
void AbstractMaterialConstantZoneStateDx9::ExtractNamesFromShader(const void* shader, const size_t shaderSize)
{
const auto shaderInfo = d3d9::ShaderAnalyser::GetShaderInfo(shader, shaderSize);
if (!shaderInfo)
return;
for (const auto& constant : shaderInfo->m_constants)
{
if (constant.m_register_set == d3d9::RegisterSet::SAMPLER)
{
if (AddTextureDefName(constant.m_name))
{
const auto samplerPos = constant.m_name.rfind(SAMPLER_STR);
if (samplerPos != std::string::npos)
{
auto nameWithoutSamplerStr = constant.m_name;
nameWithoutSamplerStr.erase(samplerPos, std::char_traits<char>::length(SAMPLER_STR));
AddTextureDefName(nameWithoutSamplerStr);
}
}
}
else
AddConstantName(constant.m_name);
}
}
void AbstractMaterialConstantZoneStateDx11::ExtractNamesFromShader(const void* shader, const size_t shaderSize)
{
const auto shaderInfo = d3d11::ShaderAnalyser::GetShaderInfo(static_cast<const uint8_t*>(shader), shaderSize);
if (!shaderInfo)
return;
const auto globalsConstantBuffer = std::ranges::find_if(std::as_const(shaderInfo->m_constant_buffers),
[](const d3d11::ConstantBuffer& constantBuffer)
{
return constantBuffer.m_name == GLOBALS_CBUFFER_NAME;
});
const auto perObjectConsts = std::ranges::find_if(std::as_const(shaderInfo->m_constant_buffers),
[](const d3d11::ConstantBuffer& constantBuffer)
{
return constantBuffer.m_name == PER_OBJECT_CONSTS_CBUFFER_NAME;
});
if (globalsConstantBuffer != shaderInfo->m_constant_buffers.end())
{
for (const auto& variable : globalsConstantBuffer->m_variables)
AddConstantName(variable.m_name);
}
if (perObjectConsts != shaderInfo->m_constant_buffers.end())
{
for (const auto& variable : perObjectConsts->m_variables)
AddConstantName(variable.m_name);
}
for (const auto& boundResource : shaderInfo->m_bound_resources)
{
if (boundResource.m_type == d3d11::BoundResourceType::SAMPLER || boundResource.m_type == d3d11::BoundResourceType::TEXTURE)
{
if (AddTextureDefName(boundResource.m_name))
{
const auto samplerPos = boundResource.m_name.rfind(SAMPLER_STR);
if (samplerPos != std::string::npos)
{
auto nameWithoutSamplerStr = boundResource.m_name;
nameWithoutSamplerStr.erase(samplerPos, std::char_traits<char>::length(SAMPLER_STR));
AddTextureDefName(nameWithoutSamplerStr);
}
}
}
}
}

View File

@ -0,0 +1,41 @@
#pragma once
#include "Dumping/IZoneAssetDumperState.h"
#include <string>
#include <unordered_map>
#include <unordered_set>
class AbstractMaterialConstantZoneState : public IZoneAssetDumperState
{
public:
void ExtractNamesFromZone();
bool GetConstantName(unsigned hash, std::string& constantName) const;
bool GetTextureDefName(unsigned hash, std::string& textureDefName) const;
protected:
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);
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;
};
class AbstractMaterialConstantZoneStateDx9 : public AbstractMaterialConstantZoneState
{
protected:
void ExtractNamesFromShader(const void* shader, size_t shaderSize) override;
};
class AbstractMaterialConstantZoneStateDx11 : public AbstractMaterialConstantZoneState
{
protected:
void ExtractNamesFromShader(const void* shader, size_t shaderSize) override;
};