From 3b59dad109b6ca89098505f6eabbfc638211f016 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 22 Sep 2024 15:10:01 +0200 Subject: [PATCH] chore: generalize material constant zone state --- src/Common/Game/T6/CommonT6.h | 5 + src/ObjCommon/Shader/D3D9ShaderAnalyser.cpp | 16 +- src/ObjCommon/Shader/D3D9ShaderAnalyser.h | 2 +- .../T6/Material/MaterialConstantZoneState.cpp | 120 +------------ .../T6/Material/MaterialConstantZoneState.h | 24 +-- .../AbstractMaterialConstantZoneState.cpp | 164 ++++++++++++++++++ .../AbstractMaterialConstantZoneState.h | 41 +++++ 7 files changed, 229 insertions(+), 143 deletions(-) create mode 100644 src/ObjWriting/Material/AbstractMaterialConstantZoneState.cpp create mode 100644 src/ObjWriting/Material/AbstractMaterialConstantZoneState.h diff --git a/src/Common/Game/T6/CommonT6.h b/src/Common/Game/T6/CommonT6.h index 98e0cc6e..9f7fbb2b 100644 --- a/src/Common/Game/T6/CommonT6.h +++ b/src/Common/Game/T6/CommonT6.h @@ -21,6 +21,11 @@ namespace T6 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) { if (!str || !*str) diff --git a/src/ObjCommon/Shader/D3D9ShaderAnalyser.cpp b/src/ObjCommon/Shader/D3D9ShaderAnalyser.cpp index 918d3c16..4872c82b 100644 --- a/src/ObjCommon/Shader/D3D9ShaderAnalyser.cpp +++ b/src/ObjCommon/Shader/D3D9ShaderAnalyser.cpp @@ -61,12 +61,12 @@ namespace d3d9 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)) return false; - const auto version = *shaderByteCode; + const auto version = *static_cast(shaderByteCode); shaderInfo.m_version_minor = version & 0xFF; shaderInfo.m_version_major = (version & 0xFF00) >> 8; @@ -91,10 +91,10 @@ namespace d3d9 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; - size_t currentOffset = sizeof(uint32_t); + const auto* currentPos = reinterpret_cast(shaderByteCode + sizeof(uint32_t)); + auto currentOffset = sizeof(uint32_t); while (*currentPos != OPCODE_END && (currentOffset + sizeof(uint32_t) - 1) < shaderByteCodeSize) { const auto currentValue = *currentPos; @@ -215,7 +215,7 @@ namespace d3d9 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)) return false; @@ -236,14 +236,14 @@ namespace d3d9 } } // namespace d3d9 -std::unique_ptr ShaderAnalyser::GetShaderInfo(const uint32_t* shaderByteCode, const size_t shaderByteCodeSize) +std::unique_ptr ShaderAnalyser::GetShaderInfo(const void* shaderByteCode, const size_t shaderByteCodeSize) { if (shaderByteCode == nullptr || shaderByteCodeSize == 0) return nullptr; auto shaderInfo = std::make_unique(); - if (!PopulateShaderInfoFromShaderByteCode(*shaderInfo, shaderByteCode, shaderByteCodeSize)) + if (!PopulateShaderInfoFromShaderByteCode(*shaderInfo, static_cast(shaderByteCode), shaderByteCodeSize)) return nullptr; return shaderInfo; diff --git a/src/ObjCommon/Shader/D3D9ShaderAnalyser.h b/src/ObjCommon/Shader/D3D9ShaderAnalyser.h index e58f1202..7e186c8d 100644 --- a/src/ObjCommon/Shader/D3D9ShaderAnalyser.h +++ b/src/ObjCommon/Shader/D3D9ShaderAnalyser.h @@ -95,6 +95,6 @@ namespace d3d9 class ShaderAnalyser { public: - static std::unique_ptr GetShaderInfo(const uint32_t* shaderByteCode, size_t shaderByteCodeSize); + static std::unique_ptr GetShaderInfo(const void* shaderByteCode, size_t shaderByteCodeSize); }; } // namespace d3d9 diff --git a/src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.cpp b/src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.cpp index f92b3783..0219063e 100644 --- a/src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.cpp +++ b/src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.cpp @@ -4,16 +4,9 @@ #include "Game/T6/GameAssetPoolT6.h" #include "Game/T6/GameT6.h" #include "ObjWriting.h" -#include "Shader/D3D11ShaderAnalyser.h" - -#include 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[]{ "AngularVelocityScale", "AnimSpeed", @@ -478,15 +471,8 @@ namespace T6 "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()) { const auto* t6AssetPools = dynamic_cast(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(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); - 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; + return Common::R_HashString(str.c_str()); } void MaterialConstantZoneState::ExtractNamesFromTechnique(const MaterialTechnique* technique) { - const auto existingTechnique = m_dumped_techniques.find(technique); - if (existingTechnique != m_dumped_techniques.end()) + if (!ShouldDumpFromStruct(technique)) return; - m_dumped_techniques.emplace(technique); - for (auto passIndex = 0u; passIndex < technique->passCount; 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(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::length(SAMPLER_STR)); - AddTextureDefName(std::move(nameWithoutSamplerStr)); - } - } - } - } - } - void MaterialConstantZoneState::AddStaticKnownNames() { for (const auto* knownConstantName : KNOWN_CONSTANT_NAMES) @@ -614,23 +521,4 @@ namespace T6 for (const auto* knownTextureDefName : KNOWN_TEXTURE_DEF_NAMES) 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 diff --git a/src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.h b/src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.h index 27f3f49e..148169eb 100644 --- a/src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.h +++ b/src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.h @@ -1,30 +1,18 @@ #pragma once -#include "Dumping/IZoneAssetDumperState.h" #include "Game/T6/T6.h" +#include "Material/AbstractMaterialConstantZoneState.h" #include -#include -#include namespace T6 { - class MaterialConstantZoneState final : public IZoneAssetDumperState + class MaterialConstantZoneState final : public AbstractMaterialConstantZoneStateDx11 { - public: - void ExtractNamesFromZone(); - bool GetConstantName(unsigned hash, std::string& constantName) const; - bool GetTextureDefName(unsigned hash, std::string& textureDefName) const; - - private: + protected: + void ExtractNamesFromZoneInternal() override; void ExtractNamesFromTechnique(const MaterialTechnique* technique); - void ExtractNamesFromShader(const char* shader, size_t shaderSize); - void AddStaticKnownNames(); - void AddConstantName(std::string constantName); - bool AddTextureDefName(std::string textureDefName); - - std::unordered_set m_dumped_techniques; - std::unordered_map m_constant_names_from_shaders; - std::unordered_map m_texture_def_names_from_shaders; + void AddStaticKnownNames() override; + unsigned HashString(const std::string& str) override; }; } // namespace T6 diff --git a/src/ObjWriting/Material/AbstractMaterialConstantZoneState.cpp b/src/ObjWriting/Material/AbstractMaterialConstantZoneState.cpp new file mode 100644 index 00000000..bdbee0c2 --- /dev/null +++ b/src/ObjWriting/Material/AbstractMaterialConstantZoneState.cpp @@ -0,0 +1,164 @@ +#include "AbstractMaterialConstantZoneState.h" + +#include "ObjWriting.h" +#include "Shader/D3D11ShaderAnalyser.h" +#include "Shader/D3D9ShaderAnalyser.h" + +#include + +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(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::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(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::length(SAMPLER_STR)); + AddTextureDefName(nameWithoutSamplerStr); + } + } + } + } +} diff --git a/src/ObjWriting/Material/AbstractMaterialConstantZoneState.h b/src/ObjWriting/Material/AbstractMaterialConstantZoneState.h new file mode 100644 index 00000000..2a7734d8 --- /dev/null +++ b/src/ObjWriting/Material/AbstractMaterialConstantZoneState.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Dumping/IZoneAssetDumperState.h" + +#include +#include +#include + +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 m_dumped_structs; + std::unordered_map m_constant_names_from_shaders; + std::unordered_map 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; +};